@ -1,11 +0,0 @@ | |||||
OPT_DEFS += -DHOST_VUSB | |||||
SRC = usbdrv.c \ | |||||
usbdrvasm.S \ | |||||
oddebug.c \ | |||||
sendchar_usart.c | |||||
SRC += $(TARGET_SRC) | |||||
# C source file search path | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv |
@ -0,0 +1,62 @@ | |||||
Time to Sleep | |||||
============= | |||||
USB suspend no activity on USB line for 3ms | |||||
No Interaction no user interaction | |||||
matrix has no change | |||||
matrix has no switch on | |||||
AVR Power Management | |||||
==================== | |||||
V-USB suspend | |||||
USB suspend | |||||
http://vusb.wikidot.com/examples | |||||
MCUSR MCU Status Register | |||||
WDRF Watchdog Reset Flag | |||||
BORF | |||||
EXTRF | |||||
PORF Power-on Reset Flag | |||||
SMCR Sleep Mode Control Register | |||||
SE Sleep Enable | |||||
SM2:0 | |||||
#define set_sleep_mode(mode) \ | |||||
#define SLEEP_MODE_IDLE (0) | |||||
#define SLEEP_MODE_ADC _BV(SM0) | |||||
#define SLEEP_MODE_PWR_DOWN _BV(SM1) | |||||
#define SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1)) | |||||
#define SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2)) | |||||
#define SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2)) | |||||
ACSR Analog Comparator Control and Status Register | |||||
To disable Analog Comparator | |||||
ACSR = 0x80; | |||||
or | |||||
ACSR &= ~_BV(ACIE); | |||||
ACSR |= _BV(ACD); | |||||
ACD: Analog Comparator Disable | |||||
When this bit is written logic one, the power to the Analog Comparator is | |||||
switched off. This bit can be set at any time to turn off the Analog | |||||
Comparator. This will reduce power consumption in Active and Idle mode. | |||||
When changing the ACD bit, the Analog Comparator Interrupt must be disabled | |||||
by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when | |||||
the bit is changed. | |||||
DIDR1 Digital Input Disable Register 1 | |||||
AIN1D | |||||
AIN0D | |||||
When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer. | |||||
PRR Power Reduction Register | |||||
PRTWI | |||||
PRTIM2 | |||||
PRTIM0 | |||||
PRTIM1 | |||||
PRSPI | |||||
PRUSART0 | |||||
PRADC |
@ -0,0 +1,40 @@ | |||||
ATMega168P Fuse/Lock Bits | |||||
========================= | |||||
This configuration is from usbasploader's Makefile. | |||||
HFUSE 0xD6 | |||||
LFUSE 0xDF | |||||
EFUSE 0x00 | |||||
LOCK 0x3F(intact) | |||||
#--------------------------------------------------------------------- | |||||
# ATMega168P | |||||
#--------------------------------------------------------------------- | |||||
# Fuse extended byte: | |||||
# 0x00 = 0 0 0 0 0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800) | |||||
# \+/ | |||||
# +------- BOOTSZ (00 = 2k bytes) | |||||
# Fuse high byte: | |||||
# 0xd6 = 1 1 0 1 0 1 1 0 | |||||
# ^ ^ ^ ^ ^ \-+-/ | |||||
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V) | |||||
# | | | | + --------- EESAVE (preserve EEPROM over chip erase) | |||||
# | | | +-------------- WDTON (if 0: watchdog always on) | |||||
# | | +---------------- SPIEN (allow serial programming) | |||||
# | +------------------ DWEN (debug wire enable) | |||||
# +-------------------- RSTDISBL (reset pin is enabled) | |||||
# Fuse low byte: | |||||
# 0xdf = 1 1 0 1 1 1 1 1 | |||||
# ^ ^ \ / \--+--/ | |||||
# | | | +------- CKSEL 3..0 (external >8M crystal) | |||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) | |||||
# | +------------------ CKOUT (if 0: Clock output enabled) | |||||
# +-------------------- CKDIV8 (if 0: divide by 8) | |||||
# Lock Bits | |||||
# 0x3f = - - 1 1 1 1 1 1 | |||||
# \ / \-/ \-/ | |||||
# | | +----- LB 2..1 (No memory lock features enabled) | |||||
# | +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section) | |||||
# +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section) |
@ -0,0 +1,91 @@ | |||||
# | |||||
# Makefile for iWRAP | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_iwrap | |||||
# Directory common source filess exist | |||||
COMMON_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
CONFIG_H = config_iwrap.h | |||||
# V-USB debug level: To use ps2_usart.c level must be 0 | |||||
# ps2_usart.c requires USART to receive PS/2 signal. | |||||
OPT_DEFS = -DDEBUG_LEVEL=0 | |||||
# MCU name, you MUST set this to match the board you are using | |||||
# type "make clean" after changing this, so all files will be rebuilt | |||||
MCU = atmega168p | |||||
# avrdude doesn't know atmega168p | |||||
AVRDUDE_MCU = atmega168 | |||||
# Processor frequency. | |||||
# Normally the first thing your program should do is set the clock prescaler, | |||||
# so your program will run at the correct speed. You should also set this | |||||
# variable to same clock speed. The _delay_ms() macro uses this, and many | |||||
# examples use this variable to calculate timings. Do not add a "UL" here. | |||||
F_CPU = 12000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
AVRDUDE = avrdude | |||||
# Type: avrdude -c ? to get a full listing. | |||||
AVRDUDE_PROGRAMMER = usbasp | |||||
AVRDUDE_PORT = | |||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex | |||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep | |||||
# Uncomment the following if you want avrdude's erase cycle counter. | |||||
# Note that this counter needs to be initialized first using -Yn, | |||||
# see avrdude manual. | |||||
#AVRDUDE_ERASE_COUNTER = -y | |||||
# Uncomment the following if you do /not/ wish a verification to be | |||||
# performed after programming the device. | |||||
#AVRDUDE_NO_VERIFY = -V | |||||
# Increase verbosity level. Please use this when submitting bug | |||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> | |||||
# to submit bug reports. | |||||
#AVRDUDE_VERBOSE = -v -v | |||||
#AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) | |||||
AVRDUDE_FLAGS = -p $(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER) | |||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) | |||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) | |||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) | |||||
PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) | |||||
# Search Path | |||||
VPATH = $(TARGET_DIR) | |||||
include $(COMMON_DIR)/iwrap.mk | |||||
# To be swatchable btween Bluetooth and USB. Comment out if you don't need USB. | |||||
include $(COMMON_DIR)/vusb.mk | |||||
include $(COMMON_DIR)/common.mk |
@ -0,0 +1,55 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBEEA | |||||
// TODO: share these strings with usbconfig.h | |||||
// Edit usbconfig.h to change these. | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT HHKB mod | |||||
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 8 | |||||
#define MATRIX_COLS 8 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* pins for Software UART */ | |||||
#define SUART_IN_PIN PINC | |||||
#define SUART_IN_BIT 5 | |||||
#define SUART_OUT_PORT PORTC | |||||
#define SUART_OUT_BIT 4 | |||||
#define DEBUG_LED 1 | |||||
#define DEBUG_LED_CONFIG (DDRD |= (1<<4)) | |||||
#define DEBUG_LED_OFF (PORTD |= (1<<4)) | |||||
#define DEBUG_LED_ON (PORTD &= ~(1<<4)) | |||||
#endif |
@ -0,0 +1,4 @@ | |||||
HHKB Bluetooth mod | |||||
================== | |||||
See this article: | |||||
http://geekhack.org/showwiki.php?title=Island:20851 |
@ -0,0 +1,2 @@ | |||||
[Picasa] | |||||
name=Bluetooth_img |
@ -0,0 +1,190 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <avr/interrupt.h> | |||||
#include "usb_keycodes.h" | |||||
#include "host.h" | |||||
#include "util.h" | |||||
#include "debug.h" | |||||
#ifdef NKRO_ENABLE | |||||
bool keyboard_nkro = false; | |||||
#endif | |||||
static host_driver_t *driver; | |||||
static report_keyboard_t report0; | |||||
static report_keyboard_t report1; | |||||
report_keyboard_t *keyboard_report = &report0; | |||||
report_keyboard_t *keyboard_report_prev = &report1; | |||||
static inline void add_key_byte(uint8_t code); | |||||
static inline void add_key_bit(uint8_t code); | |||||
void host_set_driver(host_driver_t *d) | |||||
{ | |||||
driver = d; | |||||
} | |||||
host_driver_t *host_get_driver(void) | |||||
{ | |||||
return driver; | |||||
} | |||||
uint8_t host_keyboard_leds(void) | |||||
{ | |||||
if (!driver) return 0; | |||||
return (*driver->keyboard_leds)(); | |||||
} | |||||
/* keyboard report operations */ | |||||
void host_add_key(uint8_t key) | |||||
{ | |||||
#ifdef NKRO_ENABLE | |||||
if (keyboard_nkro) { | |||||
add_key_bit(key); | |||||
return; | |||||
} | |||||
#endif | |||||
add_key_byte(key); | |||||
} | |||||
void host_add_mod_bit(uint8_t mod) | |||||
{ | |||||
keyboard_report->mods |= mod; | |||||
} | |||||
void host_set_mods(uint8_t mods) | |||||
{ | |||||
keyboard_report->mods = mods; | |||||
} | |||||
void host_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
host_add_mod_bit(MOD_BIT(code)); | |||||
} else { | |||||
host_add_key(code); | |||||
} | |||||
} | |||||
void host_swap_keyboard_report(void) | |||||
{ | |||||
uint8_t sreg = SREG; | |||||
cli(); | |||||
report_keyboard_t *tmp = keyboard_report_prev; | |||||
keyboard_report_prev = keyboard_report; | |||||
keyboard_report = tmp; | |||||
SREG = sreg; | |||||
} | |||||
void host_clear_keyboard_report(void) | |||||
{ | |||||
keyboard_report->mods = 0; | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
} | |||||
uint8_t host_has_anykey(void) | |||||
{ | |||||
uint8_t cnt = 0; | |||||
for (int i = 0; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report->keys[i]) | |||||
cnt++; | |||||
} | |||||
return cnt; | |||||
} | |||||
uint8_t host_get_first_key(void) | |||||
{ | |||||
#ifdef NKRO_ENABLE | |||||
if (keyboard_nkro) { | |||||
uint8_t i = 0; | |||||
for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++) | |||||
; | |||||
return i<<3 | biton(keyboard_report->keys[i]); | |||||
} | |||||
#endif | |||||
return keyboard_report->keys[0]; | |||||
} | |||||
void host_send_keyboard_report(void) | |||||
{ | |||||
if (!driver) return; | |||||
(*driver->send_keyboard)(keyboard_report); | |||||
} | |||||
void host_mouse_send(report_mouse_t *report) | |||||
{ | |||||
if (!driver) return; | |||||
(*driver->send_mouse)(report); | |||||
} | |||||
void host_system_send(uint16_t data) | |||||
{ | |||||
if (!driver) return; | |||||
(*driver->send_consumer)(data); | |||||
} | |||||
void host_consumer_send(uint16_t data) | |||||
{ | |||||
// TODO: this is needed? | |||||
static uint16_t last_data = 0; | |||||
if (data == last_data) return; | |||||
last_data = data; | |||||
if (!driver) return; | |||||
(*driver->send_consumer)(data); | |||||
} | |||||
static inline void add_key_byte(uint8_t code) | |||||
{ | |||||
// TODO: fix ugly code | |||||
int8_t i = 0; | |||||
int8_t empty = -1; | |||||
for (; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report_prev->keys[i] == code) { | |||||
keyboard_report->keys[i] = code; | |||||
break; | |||||
} | |||||
if (empty == -1 && | |||||
keyboard_report_prev->keys[i] == 0 && | |||||
keyboard_report->keys[i] == 0) { | |||||
empty = i; | |||||
} | |||||
} | |||||
if (i == REPORT_KEYS) { | |||||
if (empty != -1) { | |||||
keyboard_report->keys[empty] = code; | |||||
} | |||||
} | |||||
} | |||||
static inline void add_key_bit(uint8_t code) | |||||
{ | |||||
if ((code>>3) < REPORT_KEYS) { | |||||
keyboard_report->keys[code>>3] |= 1<<(code&7); | |||||
} else { | |||||
debug("add_key_bit: can't add: "); phex(code); debug("\n"); | |||||
} | |||||
} |
@ -0,0 +1,33 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef HOST_DRIVER_H | |||||
#define HOST_DRIVER_H | |||||
#include <stdint.h> | |||||
#include "report.h" | |||||
typedef struct { | |||||
uint8_t (*keyboard_leds)(void); | |||||
void (*send_keyboard)(report_keyboard_t *); | |||||
void (*send_mouse)(report_mouse_t *); | |||||
void (*send_system)(uint16_t); | |||||
void (*send_consumer)(uint16_t); | |||||
} host_driver_t; | |||||
#endif |
@ -0,0 +1,10 @@ | |||||
OPT_DEFS += -DHOST_IWRAP | |||||
SRC += iwrap.c \ | |||||
suart.S \ | |||||
sendchar_uart.c \ | |||||
uart.c | |||||
# Search Path | |||||
VPATH += $(COMMON_DIR)/iwrap |
@ -0,0 +1,376 @@ | |||||
Bulegiga WT12 | |||||
============= | |||||
WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/ | |||||
iWRAP | |||||
higher layer interface for bluetooth firmware | |||||
communicate with UART | |||||
iWRAP HID | |||||
default setting | |||||
115200 8bit/n/1/n | |||||
TODO | |||||
---- | |||||
KiCAD circuit/PCB design | |||||
power saving | |||||
AVR sleep(15ms by watch dog timer) | |||||
WT12 sleep | |||||
measuring current consumption | |||||
measuring battery life of normal usage/idle/intensive usage | |||||
software reset/bootloarder | |||||
LED indicator(chaging/paring/connecting) | |||||
license confirmation of suart.c | |||||
consumer page is not working | |||||
authenticate method/SSP | |||||
SPP keyboard support | |||||
SPP debug console support | |||||
mouse wheel feature request to Bluegiga | |||||
Problems | |||||
-------- | |||||
power consumption | |||||
no consumer page support(bug?) | |||||
no mouse wheel support | |||||
no paring management | |||||
no interactive auth method | |||||
UART hardware flow control | |||||
-------------------------- | |||||
(iWRAP4 User Guide 9.5) | |||||
Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable. | |||||
If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design: | |||||
- CTS pin must be grounded | |||||
- RTS pin must be left floating | |||||
Power Saving | |||||
------------ | |||||
power consume | |||||
without opimization: 4hr to shutdown(310mAh) | |||||
2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS | |||||
measure current consumption | |||||
HHKB keyswitch matrix board | |||||
idle | |||||
scanning | |||||
Bluegiga WT12 module | |||||
SLEEP command | |||||
deep sleep on/off in config bits | |||||
HHKB keyswich | |||||
how to power off | |||||
I/O pin configuration when sleeping | |||||
FET switch for 5V regulator | |||||
Bluetooth module | |||||
power off when in USB mode | |||||
power off by FET switch | |||||
AVR configuration | |||||
unused pins | |||||
ADC | |||||
SET CONTROL CONFIG | |||||
------------------ | |||||
SET CONTROL CONFIG 4810 | |||||
SET CONTROL CONFIG LIST | |||||
SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY | |||||
Bit14 UART low latency | |||||
Bit11 Interactive pairing mode | |||||
Bit04 Deep sleep | |||||
Reconnection | |||||
------------ | |||||
SET CONTROL AUTOCALL 1124 5000 HID | |||||
1124 HID service class | |||||
5000 interval ms | |||||
HID profile | |||||
----------- | |||||
This is needed to configure only once. | |||||
SET PROFILE HID ON | |||||
RESET | |||||
HID class | |||||
--------- | |||||
SET BT CLASS 005C0 // keyboard/mouse combined devie | |||||
Pairing Security | |||||
---------------- | |||||
Secure Simple Pairing(SSP) | |||||
SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection | |||||
SET BT SSP 3 0 // Enables SSP just works mode | |||||
for keyboard with SSP | |||||
SET BT AUTH * 0000 | |||||
SET BT SSP 2 0 | |||||
SET CONTROL CONFIG 800 | |||||
RESET | |||||
for keyboard without SSP | |||||
SET BT AUTH * 0000 | |||||
SET CONTROL CONFIG 800 | |||||
RESET | |||||
AUTH | |||||
AUTH xx:xx:xx:xx:xx:xx? // Pairing request event | |||||
AUTH xx:xx:xx:xx:xx:xx 0000 | |||||
SSP PASSKEY 78:dd:08:b7:e4:a2 ? | |||||
SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx | |||||
(SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed) | |||||
RING 0 78:dd:08:b7:e4:a2 11 HID | |||||
Connecton | |||||
RING xx:xx:xx:xx:xx:xx xx HID // connection event | |||||
KILL xx:xx:xx:xx:xx:xx | |||||
Mode | |||||
---- | |||||
Command mode | |||||
Data mode | |||||
Raw mode | |||||
(Simple mode not for a real keyboard) | |||||
Raw mode | |||||
Keyboard: | |||||
0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6 | |||||
Mouse: | |||||
0x9f, length(5), 0xa1, 0x02, buttons, X, Y | |||||
Consumer page: | |||||
0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3 | |||||
consumer page suage | |||||
Bitfield 1: | |||||
0x01 Volume Increment | |||||
0x02 Volume Decrement | |||||
0x04 Mute | |||||
0x08 Play/Pause | |||||
0x10 Scan Next Track | |||||
0x20 Scan Previous Track | |||||
0x40 Stop | |||||
0x80 Eject | |||||
Bitfield 2: | |||||
0x01 Email Reader | |||||
0x02 Application Control Search | |||||
0x04 AC Bookmarks | |||||
0x08 AC Home | |||||
0x10 AC Back | |||||
0x20 AC Forward | |||||
0x40 AC Stop | |||||
0x80 AC Refresh | |||||
Bitfield 3: | |||||
0x01 Application Launch Generic Consumer Control | |||||
0x02 AL Internet Browser | |||||
0x04 AL Calculator | |||||
0x08 AL Terminal Lock / Screensaver | |||||
0x10 AL Local Machine Browser | |||||
0x20 AC Minimize | |||||
0x40 Record | |||||
0x80 Rewind | |||||
2011/07/13 | |||||
set | |||||
SET BT BDADDR 00:07:80:47:22:14 | |||||
SET BT NAME HHKB pro BT | |||||
SET BT CLASS 0005c0 | |||||
SET BT AUTH * 0000 | |||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | |||||
SET BT LAP 9e8b33 | |||||
SET BT PAGEMODE 4 2000 1 | |||||
SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb | |||||
SET BT POWER 3 3 3 | |||||
SET BT ROLE 0 f 7d00 | |||||
SET BT SNIFF 0 20 1 8 | |||||
SET BT SSP 2 1 | |||||
SET BT MTU 667 | |||||
SET CONTROL AUTOCALL 1124 3000 HID | |||||
SET CONTROL BAUD 38400,8n1 | |||||
SET CONTROL CD 00 0 | |||||
SET CONTROL ECHO 7 | |||||
SET CONTROL ESCAPE 43 00 1 | |||||
SET CONTROL GAIN 0 5 | |||||
SET CONTROL INIT SET CONTROL MUX 0 | |||||
SET CONTROL MSC DTE 00 00 00 00 00 00 | |||||
SET CONTROL MUX 1 | |||||
SET CONTROL PIO 00 00 | |||||
SET CONTROL READY 00 | |||||
SET PROFILE HID f HID | |||||
SET | |||||
info config | |||||
!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!! | |||||
WRAP THOR AI (4.1.0 build 435) | |||||
Copyright (c) 2003-2011 Bluegiga Technologies Inc. | |||||
Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31 | |||||
AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME | |||||
- BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1) | |||||
- Bluetooth version 2.1, Power class 2 | |||||
- Loader 4279, firmware 6297 (56-bit encryption), native execution mode | |||||
- up 0 days, 06:23, 2 connections (pool 2) | |||||
- User configuration: | |||||
&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006 | |||||
&028b = 0000 0bb8 | |||||
&028d = 0001 | |||||
&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000 | |||||
&0298 = a006 | |||||
&0299 = 0000 0000 | |||||
&02a3 = 0030 0030 0030 0030 | |||||
&02a4 = 009d 0000 | |||||
&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030 | |||||
&02a7 = 0000 05c0 | |||||
&02a8 = 4910 0000 0000 | |||||
&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 | |||||
&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 | |||||
&02ad = 4848 424b 7020 6f72 4220 0054 | |||||
&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 | |||||
&02b7 = 000f 4948 0044 | |||||
&02bb = 8000 | |||||
READY. | |||||
2011/07/07 settings: | |||||
set | |||||
SET BT BDADDR 00:07:80:47:22:14 | |||||
SET BT NAME HHKB Pro BT | |||||
SET BT CLASS 0005c0 | |||||
SET BT AUTH * 000 | |||||
SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP | |||||
SET BT LAP 9e8b33 | |||||
SET BT PAGEMODE 4 2000 1 | |||||
SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6 | |||||
SET BT POWER 3 3 3 | |||||
SET BT ROLE 0 f 7d00 | |||||
SET BT SNIFF 0 20 1 8 | |||||
SET BT SSP 3 0 | |||||
SET BT MTU 667 | |||||
SET CONTROL BAUD 38400,8n1 | |||||
SET CONTROL CD 00 0 | |||||
SET CONTROL ECHO 7 | |||||
SET CONTROL ESCAPE 255 00 1 | |||||
SET CONTROL GAIN 0 5 | |||||
SET CONTROL INIT set control mux 0 | |||||
SET CONTROL MSC DTE 00 00 00 00 00 00 | |||||
SET CONTROL PREAMP 1 1 | |||||
SET CONTROL READY 00 | |||||
SET PROFILE HID HID | |||||
SET PROFILE SPP Bluetooth Serial Port | |||||
SET | |||||
info config | |||||
WRAP THOR AI (4.0.0 build 317) | |||||
Copyright (c) 2003-2010 Bluegiga Technologies Inc. | |||||
Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31 | |||||
AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME | |||||
- BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1) | |||||
- Bluetooth version 2.1, Power class 2 | |||||
- Loader 4279, firmware 6297 (56-bit encryption), native execution mode | |||||
- up 0 days, 00:00, 0 connections (pool 1) | |||||
- User configuration: | |||||
&028c = 0001 0020 0000 0001 0008 0000 | |||||
&028d = 0000 | |||||
&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041 | |||||
&0298 = c006 | |||||
&02a3 = 0030 0030 0030 | |||||
&02a4 = 009d 0000 | |||||
&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030 | |||||
&02a7 = 0000 05c0 | |||||
&02a8 = 0800 0000 0000 | |||||
&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000 | |||||
&02ad = 4848 424b 5020 6f72 4220 0054 | |||||
&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 | |||||
&02b7 = 0000 | |||||
&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074 | |||||
READY. | |||||
2011/08/23: | |||||
SET BT BDADDR 00:07:80:47:22:14 | |||||
SET BT NAME HHKB pro BT | |||||
SET BT CLASS 0005c0 | |||||
SET BT AUTH * 0000 | |||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | |||||
SET BT LAP 9e8b33 | |||||
SET BT PAGEMODE 4 2000 1 | |||||
SET BT PAIRCOUNT 4 | |||||
SET BT POWER 3 3 3 | |||||
SET BT ROLE 1 f 12c0 | |||||
SET BT SNIFF 10 2 1 8 | |||||
SET BT SSP 3 0 | |||||
SET BT MTU 667 | |||||
SET CONTROL BAUD 38400,8n1 | |||||
SET CONTROL CD 00 0 | |||||
SET CONTROL ECHO 7 | |||||
SET CONTROL ESCAPE 43 00 1 | |||||
SET CONTROL GAIN 0 5 | |||||
SET CONTROL INIT SET CONTROL MUX 0 | |||||
SET CONTROL MSC DTE 00 00 00 00 00 00 | |||||
SET CONTROL MUX 1 | |||||
SET CONTROL PIO 00 00 | |||||
SET CONTROL READY 00 | |||||
SET PROFILE HID 7 HIDKeyboardMouse | |||||
SET | |||||
SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE | |||||
2011/08/25: | |||||
SET BT BDADDR 00:07:80:47:22:14 | |||||
SET BT NAME HHKB pro BT | |||||
SET BT CLASS 0005c0 | |||||
SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP | |||||
SET BT LAP 9e8b33 | |||||
SET BT PAGEMODE 4 2000 1 | |||||
SET BT PAIRCOUNT 4 | |||||
SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28 | |||||
SET BT POWER 3 3 3 | |||||
SET BT ROLE 1 f 12c0 | |||||
SET BT SNIFF 100 20 1 8 | |||||
SET BT SSP 3 0 | |||||
SET BT MTU 667 | |||||
SET CONTROL BAUD 38400,8n1 | |||||
SET CONTROL CD 00 0 | |||||
SET CONTROL ECHO 7 | |||||
SET CONTROL ESCAPE - 20 1 | |||||
SET CONTROL GAIN 0 5 | |||||
SET CONTROL INIT SET CONTROL MUX 0 | |||||
SET CONTROL MSC DTE 00 00 00 00 00 00 | |||||
SET CONTROL MUX 1 | |||||
SET CONTROL PIO 00 00 | |||||
SET CONTROL READY 00 | |||||
SET PROFILE HID f HIDKeyboardMouse | |||||
SET | |||||
SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY | |||||
2011/09/08: | |||||
SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY | |||||
Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000). | |||||
EOF |
@ -0,0 +1,467 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* host driver for Bulegiga iWRAP */ | |||||
/* Bluegiga BT12 | |||||
* Connections | |||||
* Hardware UART Software UART BlueTooth | |||||
* PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC | |||||
* | |||||
* - Hardware UART for Debug Console to communicate iWRAP | |||||
* - Software UART for iWRAP control to send keyboard/mouse data | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <string.h> | |||||
#include <avr/interrupt.h> | |||||
#include <util/delay.h> | |||||
#include "usb_keycodes.h" | |||||
#include "suart.h" | |||||
#include "uart.h" | |||||
#include "report.h" | |||||
#include "host_driver.h" | |||||
#include "iwrap.h" | |||||
#include "print.h" | |||||
/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */ | |||||
#define MUX_HEADER(LINK, LENGTH) do { \ | |||||
xmit(0xbf); /* SOF */ \ | |||||
xmit(LINK); /* Link */ \ | |||||
xmit(0x00); /* Flags */ \ | |||||
xmit(LENGTH); /* Length */ \ | |||||
} while (0) | |||||
#define MUX_FOOTER(LINK) xmit(LINK^0xff) | |||||
static uint8_t connected = 0; | |||||
//static uint8_t channel = 1; | |||||
/* iWRAP buffer */ | |||||
#define MUX_BUF_SIZE 64 | |||||
static char buf[MUX_BUF_SIZE]; | |||||
static uint8_t snd_pos = 0; | |||||
#define MUX_RCV_BUF_SIZE 256 | |||||
static char rcv_buf[MUX_RCV_BUF_SIZE]; | |||||
static uint8_t rcv_head = 0; | |||||
static uint8_t rcv_tail = 0; | |||||
/* receive buffer */ | |||||
static void rcv_enq(char c) | |||||
{ | |||||
uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE; | |||||
if (next != rcv_tail) { | |||||
rcv_buf[rcv_head] = c; | |||||
rcv_head = next; | |||||
} | |||||
} | |||||
static char rcv_deq(void) | |||||
{ | |||||
char c = 0; | |||||
if (rcv_head != rcv_tail) { | |||||
c = rcv_buf[rcv_tail++]; | |||||
rcv_tail %= MUX_RCV_BUF_SIZE; | |||||
} | |||||
return c; | |||||
} | |||||
/* | |||||
static char rcv_peek(void) | |||||
{ | |||||
if (rcv_head == rcv_tail) | |||||
return 0; | |||||
return rcv_buf[rcv_tail]; | |||||
} | |||||
*/ | |||||
static void rcv_clear(void) | |||||
{ | |||||
rcv_tail = rcv_head = 0; | |||||
} | |||||
/* iWRAP response */ | |||||
ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK | |||||
{ | |||||
if ((SUART_IN_PIN & (1<<SUART_IN_BIT))) | |||||
return; | |||||
static volatile uint8_t mux_state = 0xff; | |||||
static volatile uint8_t mux_link = 0xff; | |||||
uint8_t c = recv(); | |||||
switch (mux_state) { | |||||
case 0xff: // SOF | |||||
if (c == 0xbf) | |||||
mux_state--; | |||||
break; | |||||
case 0xfe: // Link | |||||
mux_state--; | |||||
mux_link = c; | |||||
break; | |||||
case 0xfd: // Flags | |||||
mux_state--; | |||||
break; | |||||
case 0xfc: // Length | |||||
mux_state = c; | |||||
break; | |||||
case 0x00: | |||||
mux_state = 0xff; | |||||
mux_link = 0xff; | |||||
break; | |||||
default: | |||||
if (mux_state--) { | |||||
uart_putchar(c); | |||||
rcv_enq(c); | |||||
} | |||||
} | |||||
} | |||||
/*------------------------------------------------------------------* | |||||
* iWRAP communication | |||||
*------------------------------------------------------------------*/ | |||||
void iwrap_init(void) | |||||
{ | |||||
// reset iWRAP if in already MUX mode after AVR software-reset | |||||
iwrap_send("RESET"); | |||||
iwrap_mux_send("RESET"); | |||||
_delay_ms(3000); | |||||
iwrap_send("\r\nSET CONTROL MUX 1\r\n"); | |||||
_delay_ms(500); | |||||
iwrap_check_connection(); | |||||
} | |||||
void iwrap_mux_send(const char *s) | |||||
{ | |||||
rcv_clear(); | |||||
MUX_HEADER(0xff, strlen((char *)s)); | |||||
iwrap_send(s); | |||||
MUX_FOOTER(0xff); | |||||
} | |||||
void iwrap_send(const char *s) | |||||
{ | |||||
while (*s) | |||||
xmit(*s++); | |||||
} | |||||
/* send buffer */ | |||||
void iwrap_buf_add(uint8_t c) | |||||
{ | |||||
// need space for '\0' | |||||
if (snd_pos < MUX_BUF_SIZE-1) | |||||
buf[snd_pos++] = c; | |||||
} | |||||
void iwrap_buf_del(void) | |||||
{ | |||||
if (snd_pos) | |||||
snd_pos--; | |||||
} | |||||
void iwrap_buf_send(void) | |||||
{ | |||||
buf[snd_pos] = '\0'; | |||||
snd_pos = 0; | |||||
iwrap_mux_send(buf); | |||||
} | |||||
void iwrap_call(void) | |||||
{ | |||||
char *p; | |||||
iwrap_mux_send("SET BT PAIR"); | |||||
_delay_ms(500); | |||||
p = rcv_buf + rcv_tail; | |||||
while (!strncmp(p, "SET BT PAIR", 11)) { | |||||
p += 7; | |||||
strncpy(p, "CALL", 4); | |||||
strncpy(p+22, " 11 HID\n\0", 9); | |||||
print_S(p); | |||||
iwrap_mux_send(p); | |||||
// TODO: skip to next line | |||||
p += 57; | |||||
DEBUG_LED_CONFIG; | |||||
DEBUG_LED_ON; | |||||
_delay_ms(500); | |||||
DEBUG_LED_OFF; | |||||
_delay_ms(500); | |||||
DEBUG_LED_ON; | |||||
_delay_ms(500); | |||||
DEBUG_LED_OFF; | |||||
_delay_ms(500); | |||||
DEBUG_LED_ON; | |||||
_delay_ms(500); | |||||
DEBUG_LED_OFF; | |||||
_delay_ms(500); | |||||
DEBUG_LED_ON; | |||||
_delay_ms(500); | |||||
DEBUG_LED_OFF; | |||||
_delay_ms(500); | |||||
DEBUG_LED_ON; | |||||
_delay_ms(500); | |||||
DEBUG_LED_OFF; | |||||
_delay_ms(500); | |||||
} | |||||
iwrap_check_connection(); | |||||
} | |||||
void iwrap_kill(void) | |||||
{ | |||||
char c; | |||||
iwrap_mux_send("LIST"); | |||||
_delay_ms(500); | |||||
while ((c = rcv_deq()) && c != '\n') ; | |||||
if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) { | |||||
print("no connection to kill.\n"); | |||||
return; | |||||
} | |||||
// skip 10 'space' chars | |||||
for (uint8_t i = 10; i; i--) | |||||
while ((c = rcv_deq()) && c != ' ') ; | |||||
char *p = rcv_buf + rcv_tail - 5; | |||||
strncpy(p, "KILL ", 5); | |||||
strncpy(p + 22, "\n\0", 2); | |||||
print_S(p); | |||||
iwrap_mux_send(p); | |||||
_delay_ms(500); | |||||
iwrap_check_connection(); | |||||
} | |||||
void iwrap_unpair(void) | |||||
{ | |||||
iwrap_mux_send("SET BT PAIR"); | |||||
_delay_ms(500); | |||||
char *p = rcv_buf + rcv_tail; | |||||
if (!strncmp(p, "SET BT PAIR", 11)) { | |||||
strncpy(p+29, "\n\0", 2); | |||||
print_S(p); | |||||
iwrap_mux_send(p); | |||||
} | |||||
} | |||||
void iwrap_sleep(void) | |||||
{ | |||||
iwrap_mux_send("SLEEP"); | |||||
} | |||||
void iwrap_sniff(void) | |||||
{ | |||||
} | |||||
void iwrap_subrate(void) | |||||
{ | |||||
} | |||||
bool iwrap_failed(void) | |||||
{ | |||||
if (strncmp(rcv_buf, "SYNTAX ERROR", 12)) | |||||
return true; | |||||
else | |||||
return false; | |||||
} | |||||
uint8_t iwrap_connected(void) | |||||
{ | |||||
return connected; | |||||
} | |||||
uint8_t iwrap_check_connection(void) | |||||
{ | |||||
iwrap_mux_send("LIST"); | |||||
_delay_ms(100); | |||||
if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6)) | |||||
connected = 0; | |||||
else | |||||
connected = 1; | |||||
return connected; | |||||
} | |||||
/*------------------------------------------------------------------* | |||||
* Host driver | |||||
*------------------------------------------------------------------*/ | |||||
static uint8_t keyboard_leds(void); | |||||
static void send_keyboard(report_keyboard_t *report); | |||||
static void send_mouse(report_mouse_t *report); | |||||
static void send_system(uint16_t data); | |||||
static void send_consumer(uint16_t data); | |||||
static host_driver_t driver = { | |||||
keyboard_leds, | |||||
send_keyboard, | |||||
send_mouse, | |||||
send_system, | |||||
send_consumer | |||||
}; | |||||
host_driver_t *iwrap_driver(void) | |||||
{ | |||||
return &driver; | |||||
} | |||||
static uint8_t keyboard_leds(void) { | |||||
return 0; | |||||
} | |||||
static void send_keyboard(report_keyboard_t *report) | |||||
{ | |||||
if (!iwrap_connected() && !iwrap_check_connection()) return; | |||||
MUX_HEADER(0x01, 0x0c); | |||||
// HID raw mode header | |||||
xmit(0x9f); | |||||
xmit(0x0a); // Length | |||||
xmit(0xa1); // keyboard report | |||||
xmit(0x01); | |||||
xmit(report->mods); | |||||
xmit(0x00); // reserved byte(always 0) | |||||
xmit(report->keys[0]); | |||||
xmit(report->keys[1]); | |||||
xmit(report->keys[2]); | |||||
xmit(report->keys[3]); | |||||
xmit(report->keys[4]); | |||||
xmit(report->keys[5]); | |||||
MUX_FOOTER(0x01); | |||||
} | |||||
static void send_mouse(report_mouse_t *report) | |||||
{ | |||||
#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE) | |||||
if (!iwrap_connected() && !iwrap_check_connection()) return; | |||||
MUX_HEADER(0x01, 0x07); | |||||
// HID raw mode header | |||||
xmit(0x9f); | |||||
xmit(0x05); // Length | |||||
xmit(0xa1); // mouse report | |||||
xmit(0x02); | |||||
xmit(report->buttons); | |||||
xmit(report->x); | |||||
xmit(report->y); | |||||
MUX_FOOTER(0x01); | |||||
#endif | |||||
} | |||||
static void send_system(uint16_t data) | |||||
{ | |||||
/* not supported */ | |||||
} | |||||
static void send_consumer(uint16_t data) | |||||
{ | |||||
#ifdef EXTRAKEY_ENABLE | |||||
static uint16_t last_data = 0; | |||||
uint8_t bits1 = 0; | |||||
uint8_t bits2 = 0; | |||||
uint8_t bits3 = 0; | |||||
if (!iwrap_connected() && !iwrap_check_connection()) return; | |||||
if (data == last_data) return; | |||||
last_data = data; | |||||
// 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) | |||||
switch (data) { | |||||
case AUDIO_VOL_UP: | |||||
bits1 = 0x01; | |||||
break; | |||||
case AUDIO_VOL_DOWN: | |||||
bits1 = 0x02; | |||||
break; | |||||
case AUDIO_MUTE: | |||||
bits1 = 0x04; | |||||
break; | |||||
case TRANSPORT_PLAY_PAUSE: | |||||
bits1 = 0x08; | |||||
break; | |||||
case TRANSPORT_NEXT_TRACK: | |||||
bits1 = 0x10; | |||||
break; | |||||
case TRANSPORT_PREV_TRACK: | |||||
bits1 = 0x20; | |||||
break; | |||||
case TRANSPORT_STOP: | |||||
bits1 = 0x40; | |||||
break; | |||||
case TRANSPORT_EJECT: | |||||
bits1 = 0x80; | |||||
break; | |||||
case AL_EMAIL: | |||||
bits2 = 0x01; | |||||
break; | |||||
case AC_SEARCH: | |||||
bits2 = 0x02; | |||||
break; | |||||
case AC_BOOKMARKS: | |||||
bits2 = 0x04; | |||||
break; | |||||
case AC_HOME: | |||||
bits2 = 0x08; | |||||
break; | |||||
case AC_BACK: | |||||
bits2 = 0x10; | |||||
break; | |||||
case AC_FORWARD: | |||||
bits2 = 0x20; | |||||
break; | |||||
case AC_STOP: | |||||
bits2 = 0x40; | |||||
break; | |||||
case AC_REFRESH: | |||||
bits2 = 0x80; | |||||
break; | |||||
case AL_CC_CONFIG: | |||||
bits3 = 0x01; | |||||
break; | |||||
case AL_CALCULATOR: | |||||
bits3 = 0x04; | |||||
break; | |||||
case AL_LOCK: | |||||
bits3 = 0x08; | |||||
break; | |||||
case AL_LOCAL_BROWSER: | |||||
bits3 = 0x10; | |||||
break; | |||||
case AC_MINIMIZE: | |||||
bits3 = 0x20; | |||||
break; | |||||
case TRANSPORT_RECORD: | |||||
bits3 = 0x40; | |||||
break; | |||||
case TRANSPORT_REWIND: | |||||
bits3 = 0x80; | |||||
break; | |||||
} | |||||
MUX_HEADER(0x01, 0x07); | |||||
xmit(0x9f); | |||||
xmit(0x05); // Length | |||||
xmit(0xa1); // consumer report | |||||
xmit(0x03); | |||||
xmit(bits1); | |||||
xmit(bits2); | |||||
xmit(bits3); | |||||
MUX_FOOTER(0x01); | |||||
#endif | |||||
} |
@ -0,0 +1,49 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef IWRAP_H | |||||
#define IWRAP_H | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include "host_driver.h" | |||||
/* enable iWRAP MUX mode */ | |||||
#define MUX_MODE | |||||
host_driver_t *iwrap_driver(void); | |||||
void iwrap_init(void); | |||||
void iwrap_send(const char *s); | |||||
void iwrap_mux_send(const char *s); | |||||
void iwrap_buf_send(void); | |||||
void iwrap_buf_add(uint8_t c); | |||||
void iwrap_buf_del(void); | |||||
void iwrap_call(void); | |||||
void iwrap_kill(void); | |||||
void iwrap_unpair(void); | |||||
void iwrap_sleep(void); | |||||
void iwrap_sniff(void); | |||||
void iwrap_subrate(void); | |||||
bool iwrap_failed(void); | |||||
uint8_t iwrap_connected(void); | |||||
uint8_t iwrap_check_connection(void); | |||||
#endif |
@ -0,0 +1,378 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <avr/interrupt.h> | |||||
#include <avr/io.h> | |||||
//#include <avr/wdt.h> | |||||
#include "wd.h" // in order to use watchdog in interrupt mode | |||||
#include <avr/sleep.h> | |||||
#include <util/delay.h> | |||||
#include <avr/power.h> | |||||
#include "keyboard.h" | |||||
#include "matrix.h" | |||||
#include "host.h" | |||||
#include "iwrap.h" | |||||
#ifdef HOST_VUSB | |||||
# include "vusb.h" | |||||
# include "usbdrv.h" | |||||
#endif | |||||
#include "uart.h" | |||||
#include "suart.h" | |||||
#include "timer.h" | |||||
#include "debug.h" | |||||
#include "usb_keycodes.h" | |||||
#include "command.h" | |||||
static void sleep(uint8_t term); | |||||
static bool console(void); | |||||
static uint8_t console_command(uint8_t c); | |||||
static uint8_t key2asc(uint8_t key); | |||||
/* | |||||
static void set_prr(void) | |||||
{ | |||||
power_adc_disable(); | |||||
power_spi_disable(); | |||||
power_twi_disable(); | |||||
#ifndef TIMER_H | |||||
//power_timer0_disable(); // used in timer.c | |||||
#endif | |||||
power_timer1_disable(); | |||||
power_timer2_disable(); | |||||
} | |||||
*/ | |||||
/* | |||||
static void pullup_pins(void) | |||||
{ | |||||
// DDRs are set to 0(input) by default. | |||||
#ifdef PORTA | |||||
PORTA = 0xFF; | |||||
#endif | |||||
PORTB = 0xFF; | |||||
PORTC = 0xFF; | |||||
PORTD = 0xFF; | |||||
#ifdef PORTE | |||||
PORTE = 0xFF; | |||||
#endif | |||||
#ifdef PORTE | |||||
PORTF = 0xFF; | |||||
#endif | |||||
} | |||||
*/ | |||||
#ifdef HOST_VUSB | |||||
static void disable_vusb(void) | |||||
{ | |||||
// disable interrupt & disconnect to prevent host from enumerating | |||||
USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); | |||||
usbDeviceDisconnect(); | |||||
} | |||||
static void enable_vusb(void) | |||||
{ | |||||
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); | |||||
usbDeviceConnect(); | |||||
} | |||||
static void init_vusb(void) | |||||
{ | |||||
uint8_t i = 0; | |||||
usbInit(); | |||||
disable_vusb(); | |||||
/* fake USB disconnect for > 250 ms */ | |||||
while(--i){ | |||||
_delay_ms(1); | |||||
} | |||||
enable_vusb(); | |||||
} | |||||
#endif | |||||
void change_driver(host_driver_t *driver) | |||||
{ | |||||
host_clear_keyboard_report(); | |||||
host_swap_keyboard_report(); | |||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
_delay_ms(1000); | |||||
host_set_driver(driver); | |||||
} | |||||
static bool sleeping = false; | |||||
static bool insomniac = false; // TODO: should be false for power saving | |||||
static uint16_t last_timer = 0; | |||||
int main(void) | |||||
{ | |||||
MCUSR = 0; | |||||
clock_prescale_set(clock_div_1); | |||||
WD_SET(WD_OFF); | |||||
// power saving: the result is worse than nothing... why? | |||||
//pullup_pins(); | |||||
//set_prr(); | |||||
print_enable = true; | |||||
debug_enable = false; | |||||
#ifdef HOST_VUSB | |||||
disable_vusb(); | |||||
#endif | |||||
uart_init(115200); | |||||
keyboard_init(); | |||||
print("\nSend BREAK for UART Console Commands.\n"); | |||||
// TODO: move to iWRAP/suart file | |||||
print("suart init\n"); | |||||
// suart init | |||||
// PC4: Tx Output IDLE(Hi) | |||||
PORTC |= (1<<4); | |||||
DDRC |= (1<<4); | |||||
// PC5: Rx Input(pull-up) | |||||
PORTC |= (1<<5); | |||||
DDRC &= ~(1<<5); | |||||
// suart receive interrut(PC5/PCINT13) | |||||
PCMSK1 = 0b00100000; | |||||
PCICR = 0b00000010; | |||||
host_set_driver(iwrap_driver()); | |||||
print("iwrap_init()\n"); | |||||
iwrap_init(); | |||||
iwrap_call(); | |||||
last_timer = timer_read(); | |||||
while (true) { | |||||
#ifdef HOST_VUSB | |||||
if (host_get_driver() == vusb_driver()) | |||||
usbPoll(); | |||||
#endif | |||||
keyboard_proc(); | |||||
#ifdef HOST_VUSB | |||||
if (host_get_driver() == vusb_driver()) | |||||
vusb_transfer_keyboard(); | |||||
#endif | |||||
if (matrix_is_modified() || console()) { | |||||
last_timer = timer_read(); | |||||
sleeping = false; | |||||
} else if (!sleeping && timer_elapsed(last_timer) > 4000) { | |||||
sleeping = true; | |||||
iwrap_check_connection(); | |||||
} | |||||
if (host_get_driver() == iwrap_driver()) { | |||||
if (sleeping && !insomniac) { | |||||
_delay_ms(1); // wait for UART to send | |||||
iwrap_sleep(); | |||||
sleep(WDTO_60MS); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
static void sleep(uint8_t term) | |||||
{ | |||||
WD_SET(WD_IRQ, term); | |||||
cli(); | |||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |||||
sleep_enable(); | |||||
sleep_bod_disable(); | |||||
sei(); | |||||
sleep_cpu(); | |||||
sleep_disable(); | |||||
WD_SET(WD_OFF); | |||||
} | |||||
ISR(WDT_vect) | |||||
{ | |||||
// wake up | |||||
} | |||||
static bool console(void) | |||||
{ | |||||
// Send to Bluetoot module WT12 | |||||
static bool breaked = false; | |||||
if (!uart_available()) | |||||
return false; | |||||
else { | |||||
uint8_t c; | |||||
c = uart_getchar(); | |||||
uart_putchar(c); | |||||
switch (c) { | |||||
case 0x00: // BREAK signal | |||||
if (!breaked) { | |||||
print("break(? for help): "); | |||||
breaked = true; | |||||
} | |||||
break; | |||||
case '\r': | |||||
uart_putchar('\n'); | |||||
iwrap_buf_send(); | |||||
break; | |||||
case '\b': | |||||
iwrap_buf_del(); | |||||
break; | |||||
default: | |||||
if (breaked) { | |||||
print("\n"); | |||||
console_command(c); | |||||
breaked = false; | |||||
} else { | |||||
iwrap_buf_add(c); | |||||
} | |||||
break; | |||||
} | |||||
return true; | |||||
} | |||||
} | |||||
uint8_t command_extra() | |||||
{ | |||||
return console_command(key2asc(host_get_first_key())); | |||||
} | |||||
static uint8_t console_command(uint8_t c) | |||||
{ | |||||
switch (c) { | |||||
case 'h': | |||||
case '?': | |||||
print("\nCommands for Bluetooth(WT12/iWRAP):\n"); | |||||
print("r: reset. software reset by watchdog\n"); | |||||
print("i: insomniac. prevent KB from sleeping\n"); | |||||
print("c: iwrap_call. CALL for BT connection.\n"); | |||||
#ifdef HOST_VUSB | |||||
print("u: USB mode. switch to USB.\n"); | |||||
print("w: BT mode. switch to Bluetooth.\n"); | |||||
#endif | |||||
print("k: kill first connection.\n"); | |||||
print("Del: unpair first pairing.\n"); | |||||
print("\n"); | |||||
return 0; | |||||
case 'r': | |||||
print("reset\n"); | |||||
WD_AVR_RESET(); | |||||
return 1; | |||||
case 'i': | |||||
insomniac = !insomniac; | |||||
if (insomniac) | |||||
print("insomniac\n"); | |||||
else | |||||
print("not insomniac\n"); | |||||
return 1; | |||||
case 'c': | |||||
print("iwrap_call()\n"); | |||||
iwrap_call(); | |||||
return 1; | |||||
#ifdef HOST_VUSB | |||||
case 'u': | |||||
print("USB mode\n"); | |||||
init_vusb(); | |||||
change_driver(vusb_driver()); | |||||
//iwrap_kill(); | |||||
//iwrap_sleep(); | |||||
// disable suart receive interrut(PC5/PCINT13) | |||||
PCMSK1 &= ~(0b00100000); | |||||
PCICR &= ~(0b00000010); | |||||
return 1; | |||||
case 'w': | |||||
print("iWRAP mode\n"); | |||||
change_driver(iwrap_driver()); | |||||
disable_vusb(); | |||||
// enable suart receive interrut(PC5/PCINT13) | |||||
PCMSK1 |= 0b00100000; | |||||
PCICR |= 0b00000010; | |||||
return 1; | |||||
#endif | |||||
case 'k': | |||||
print("kill\n"); | |||||
iwrap_kill(); | |||||
return 1; | |||||
case 0x7F: // DELETE | |||||
print("unpair\n"); | |||||
iwrap_unpair(); | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
// convert keycode into ascii charactor | |||||
static uint8_t key2asc(uint8_t key) | |||||
{ | |||||
switch (key) { | |||||
case KB_A: return 'a'; | |||||
case KB_B: return 'b'; | |||||
case KB_C: return 'c'; | |||||
case KB_D: return 'd'; | |||||
case KB_E: return 'e'; | |||||
case KB_F: return 'f'; | |||||
case KB_G: return 'g'; | |||||
case KB_H: return 'h'; | |||||
case KB_I: return 'i'; | |||||
case KB_J: return 'j'; | |||||
case KB_K: return 'k'; | |||||
case KB_L: return 'l'; | |||||
case KB_M: return 'm'; | |||||
case KB_N: return 'n'; | |||||
case KB_O: return 'o'; | |||||
case KB_P: return 'p'; | |||||
case KB_Q: return 'q'; | |||||
case KB_R: return 'r'; | |||||
case KB_S: return 's'; | |||||
case KB_T: return 't'; | |||||
case KB_U: return 'u'; | |||||
case KB_V: return 'v'; | |||||
case KB_W: return 'w'; | |||||
case KB_X: return 'x'; | |||||
case KB_Y: return 'y'; | |||||
case KB_Z: return 'z'; | |||||
case KB_1: return '1'; | |||||
case KB_2: return '2'; | |||||
case KB_3: return '3'; | |||||
case KB_4: return '4'; | |||||
case KB_5: return '5'; | |||||
case KB_6: return '6'; | |||||
case KB_7: return '7'; | |||||
case KB_8: return '8'; | |||||
case KB_9: return '9'; | |||||
case KB_0: return '0'; | |||||
case KB_ENTER: return '\n'; | |||||
case KB_ESCAPE: return 0x1B; | |||||
case KB_BSPACE: return '\b'; | |||||
case KB_TAB: return '\t'; | |||||
case KB_SPACE: return ' '; | |||||
case KB_MINUS: return '-'; | |||||
case KB_EQUAL: return '='; | |||||
case KB_LBRACKET: return '['; | |||||
case KB_RBRACKET: return ']'; | |||||
case KB_BSLASH: return '\\'; | |||||
case KB_NONUS_HASH: return '\\'; | |||||
case KB_SCOLON: return ';'; | |||||
case KB_QUOTE: return '\''; | |||||
case KB_GRAVE: return '`'; | |||||
case KB_COMMA: return ','; | |||||
case KB_DOT: return '.'; | |||||
case KB_SLASH: return '/'; | |||||
default: return 0x00; | |||||
} | |||||
} |
@ -0,0 +1,156 @@ | |||||
;---------------------------------------------------------------------------; | |||||
; Software implemented UART module ; | |||||
; (C)ChaN, 2005 (http://elm-chan.org/) ; | |||||
;---------------------------------------------------------------------------; | |||||
; Bit rate settings: | |||||
; | |||||
; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz | |||||
; 2.4kbps 138 - - - - - - - - | |||||
; 4.8kbps 68 138 - - - - - - - | |||||
; 9.6kbps 33 68 138 208 - - - - - | |||||
; 19.2kbps - 33 68 102 138 173 208 - - | |||||
; 38.4kbps - - 33 50 68 85 102 138 172 | |||||
; 57.6kbps - - 21 33 44 56 68 91 114 | |||||
; 115.2kbps - - - - 21 27 33 44 56 | |||||
.nolist | |||||
#include <avr/io.h> | |||||
.list | |||||
#define BPS 102 /* Bit delay. (see above table) */ | |||||
#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */ | |||||
#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */ | |||||
#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */ | |||||
#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */ | |||||
#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */ | |||||
#ifdef SPM_PAGESIZE | |||||
.macro _LPMI reg | |||||
lpm \reg, Z+ | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
movw \dl, \sl | |||||
.endm | |||||
#else | |||||
.macro _LPMI reg | |||||
lpm | |||||
mov \reg, r0 | |||||
adiw ZL, 1 | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
mov \dl, \sl | |||||
mov \dh, \sh | |||||
.endm | |||||
#endif | |||||
;---------------------------------------------------------------------------; | |||||
; Transmit a byte in serial format of N81 | |||||
; | |||||
;Prototype: void xmit (uint8_t data); | |||||
;Size: 16 words | |||||
.global xmit | |||||
.func xmit | |||||
xmit: | |||||
#if BIDIR | |||||
ldi r23, BPS-1 ;Pre-idle time for bidirectional data line | |||||
5: dec r23 ; | |||||
brne 5b ;/ | |||||
#endif | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
com r24 ;C = start bit | |||||
ldi r25, 10 ;Bit counter | |||||
cli ;Start critical section | |||||
1: ldi r23, BPS-1 ;----- Bit transferring loop | |||||
2: dec r23 ;Wait for a bit time | |||||
brne 2b ;/ | |||||
brcs 3f ;MISO = bit to be sent | |||||
OUT_1 ; | |||||
3: brcc 4f ; | |||||
OUT_0 ;/ | |||||
4: lsr r24 ;Get next bit into C | |||||
dec r25 ;All bits sent? | |||||
brne 1b ; no, coutinue | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc | |||||
;---------------------------------------------------------------------------; | |||||
; Receive a byte | |||||
; | |||||
;Prototype: uint8_t rcvr (void); | |||||
;Size: 19 words | |||||
.global rcvr | |||||
.func rcvr | |||||
rcvr: | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
ldi r24, 0x80 ;Receiving shift reg | |||||
cli ;Start critical section | |||||
1: SKIP_IN_1 ;Wait for idle | |||||
rjmp 1b | |||||
2: SKIP_IN_0 ;Wait for start bit | |||||
rjmp 2b | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
3: dec r25 | |||||
brne 3b | |||||
4: ldi r25, BPS ;----- Bit receiving loop | |||||
5: dec r25 ;Wait for a bit time | |||||
brne 5b ;/ | |||||
lsr r24 ;Next bit | |||||
SKIP_IN_0 ;Get a data bit into r24.7 | |||||
ori r24, 0x80 | |||||
brcc 4b ;All bits received? no, continue | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc | |||||
; Not wait for start bit. This should be called after detecting start bit. | |||||
.global recv | |||||
.func recv | |||||
recv: | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
ldi r24, 0x80 ;Receiving shift reg | |||||
cli ;Start critical section | |||||
;1: SKIP_IN_1 ;Wait for idle | |||||
; rjmp 1b | |||||
;2: SKIP_IN_0 ;Wait for start bit | |||||
; rjmp 2b | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
3: dec r25 | |||||
brne 3b | |||||
4: ldi r25, BPS ;----- Bit receiving loop | |||||
5: dec r25 ;Wait for a bit time | |||||
brne 5b ;/ | |||||
lsr r24 ;Next bit | |||||
SKIP_IN_0 ;Get a data bit into r24.7 | |||||
ori r24, 0x80 | |||||
brcc 4b ;All bits received? no, continue | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
6: dec r25 | |||||
brne 6b | |||||
7: SKIP_IN_1 ;Wait for stop bit | |||||
rjmp 7b | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc |
@ -0,0 +1,8 @@ | |||||
#ifndef SUART | |||||
#define SUART | |||||
void xmit(uint8_t); | |||||
uint8_t rcvr(void); | |||||
uint8_t recv(void); | |||||
#endif /* SUART */ |
@ -0,0 +1,159 @@ | |||||
/* This is from http://www.mtcnet.net/~henryvm/wdt/ */ | |||||
#ifndef _AVR_WD_H_ | |||||
#define _AVR_WD_H_ | |||||
#include <avr/io.h> | |||||
/* | |||||
Copyright (c) 2009, Curt Van Maanen | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
copyright notice and this permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
include usage- | |||||
#include "wd.h" //if in same directory as project | |||||
#include <avr/wd.h> //if wd.h is in avr directory | |||||
set watchdog modes and prescale | |||||
usage- | |||||
WD_SET(mode,[timeout]); //prescale always set | |||||
modes- | |||||
WD_OFF disabled | |||||
WD_RST normal reset mode | |||||
WD_IRQ interrupt only mode (if supported) | |||||
WD_RST_IRQ interrupt+reset mode (if supported) | |||||
timeout- | |||||
WDTO_15MS default if no timeout provided | |||||
WDTO_30MS | |||||
WDTO_60MS | |||||
WDTO_120MS | |||||
WDTO_250MS | |||||
WDTO_500MS | |||||
WDTO_1S | |||||
WDTO_2S | |||||
WDTO_4S (if supported) | |||||
WDTO_8S (if supported) | |||||
examples- | |||||
WD_SET(WD_RST,WDTO_1S); //reset mode, 1s timeout | |||||
WD_SET(WD_OFF); //watchdog disabled (if not fused on) | |||||
WD_SET(WD_RST); //reset mode, 15ms (default timeout) | |||||
WD_SET(WD_IRQ,WDTO_120MS); //interrupt only mode, 120ms timeout | |||||
WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout | |||||
for enhanced watchdogs, if the watchdog is not being used WDRF should be | |||||
cleared on every power up or reset, along with disabling the watchdog- | |||||
WD_DISABLE(); //clear WDRF, then turn off watchdog | |||||
*/ | |||||
//reset registers to the same name (MCUCSR) | |||||
#if !defined(MCUCSR) | |||||
#define MCUCSR MCUSR | |||||
#endif | |||||
//watchdog registers to the same name (WDTCSR) | |||||
#if !defined(WDTCSR) | |||||
#define WDTCSR WDTCR | |||||
#endif | |||||
//if enhanced watchdog, define irq values, create disable macro | |||||
#if defined(WDIF) | |||||
#define WD_IRQ 0xC0 | |||||
#define WD_RST_IRQ 0xC8 | |||||
#define WD_DISABLE() do{ \ | |||||
MCUCSR &= ~(1<<WDRF); \ | |||||
WD_SET(WD_OFF); \ | |||||
}while(0) | |||||
#endif | |||||
//all watchdogs | |||||
#define WD_RST 8 | |||||
#define WD_OFF 0 | |||||
//prescale values | |||||
#define WDTO_15MS 0 | |||||
#define WDTO_30MS 1 | |||||
#define WDTO_60MS 2 | |||||
#define WDTO_120MS 3 | |||||
#define WDTO_250MS 4 | |||||
#define WDTO_500MS 5 | |||||
#define WDTO_1S 6 | |||||
#define WDTO_2S 7 | |||||
//prescale values for avrs with WDP3 | |||||
#if defined(WDP3) | |||||
#define WDTO_4S 0x20 | |||||
#define WDTO_8S 0x21 | |||||
#endif | |||||
//watchdog reset | |||||
#define WDR() __asm__ __volatile__("wdr") | |||||
//avr reset using watchdog | |||||
#define WD_AVR_RESET() do{ \ | |||||
__asm__ __volatile__("cli"); \ | |||||
WD_SET_UNSAFE(WD_RST); \ | |||||
while(1); \ | |||||
}while(0) | |||||
/*set the watchdog- | |||||
1. save SREG | |||||
2. turn off irq's | |||||
3. reset watchdog timer | |||||
4. enable watchdog change | |||||
5. write watchdog value | |||||
6. restore SREG (restoring irq status) | |||||
*/ | |||||
#define WD_SET(val,...) \ | |||||
__asm__ __volatile__( \ | |||||
"in __tmp_reg__,__SREG__" "\n\t" \ | |||||
"cli" "\n\t" \ | |||||
"wdr" "\n\t" \ | |||||
"sts %[wdreg],%[wden]" "\n\t" \ | |||||
"sts %[wdreg],%[wdval]" "\n\t" \ | |||||
"out __SREG__,__tmp_reg__" "\n\t" \ | |||||
: \ | |||||
: [wdreg] "M" (&WDTCSR), \ | |||||
[wden] "r" ((uint8_t)(0x18)), \ | |||||
[wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \ | |||||
: "r0" \ | |||||
) | |||||
/*set the watchdog when I bit in SREG known to be clear- | |||||
1. reset watchdog timer | |||||
2. enable watchdog change | |||||
5. write watchdog value | |||||
*/ | |||||
#define WD_SET_UNSAFE(val,...) \ | |||||
__asm__ __volatile__( \ | |||||
"wdr" "\n\t" \ | |||||
"sts %[wdreg],%[wden]" "\n\t" \ | |||||
"sts %[wdreg],%[wdval]" "\n\t" \ | |||||
: \ | |||||
: [wdreg] "M" (&WDTCSR), \ | |||||
[wden] "r" ((uint8_t)(0x18)), \ | |||||
[wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \ | |||||
) | |||||
//for compatibility with avr/wdt.h | |||||
#define wdt_enable(val) WD_SET(WD_RST,val) | |||||
#define wdt_disable() WD_SET(WD_OFF) | |||||
#endif /* _AVR_WD_H_ */ |
@ -1,58 +0,0 @@ | |||||
/* Name: main.c | |||||
* Project: hid-mouse, a very simple HID example | |||||
* Author: Christian Starkjohann | |||||
* Creation Date: 2008-04-07 | |||||
* Tabsize: 4 | |||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH | |||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | |||||
* This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <avr/wdt.h> | |||||
#include <avr/interrupt.h> | |||||
#include <util/delay.h> | |||||
#include "usbdrv.h" | |||||
#include "oddebug.h" | |||||
#include "host_vusb.h" | |||||
#include "keyboard.h" | |||||
#if 0 | |||||
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) | |||||
#define DEBUGP(x) do { PORTC = x; } while (0) | |||||
#else | |||||
#define DEBUGP_INIT() | |||||
#define DEBUGP(x) | |||||
#endif | |||||
int main(void) | |||||
{ | |||||
DEBUGP_INIT(); | |||||
wdt_enable(WDTO_1S); | |||||
odDebugInit(); | |||||
usbInit(); | |||||
/* enforce re-enumeration, do this while interrupts are disabled! */ | |||||
usbDeviceDisconnect(); | |||||
uint8_t i = 0; | |||||
/* fake USB disconnect for > 250 ms */ | |||||
while(--i){ | |||||
wdt_reset(); | |||||
_delay_ms(1); | |||||
} | |||||
usbDeviceConnect(); | |||||
keyboard_init(); | |||||
sei(); | |||||
while (1) { | |||||
DEBUGP(0x1); | |||||
wdt_reset(); | |||||
usbPoll(); | |||||
DEBUGP(0x2); | |||||
keyboard_proc(); | |||||
DEBUGP(0x3); | |||||
host_vusb_keyboard_send(); | |||||
} | |||||
} |
@ -0,0 +1,76 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include "usb_keyboard.h" | |||||
#include "usb_mouse.h" | |||||
#include "usb_extra.h" | |||||
#include "host_driver.h" | |||||
#include "pjrc.h" | |||||
/*------------------------------------------------------------------* | |||||
* Host driver | |||||
*------------------------------------------------------------------*/ | |||||
static uint8_t keyboard_leds(void); | |||||
static void send_keyboard(report_keyboard_t *report); | |||||
static void send_mouse(report_mouse_t *report); | |||||
static void send_system(uint16_t data); | |||||
static void send_consumer(uint16_t data); | |||||
static host_driver_t driver = { | |||||
keyboard_leds, | |||||
send_keyboard, | |||||
send_mouse, | |||||
send_system, | |||||
send_consumer | |||||
}; | |||||
host_driver_t *pjrc_driver(void) | |||||
{ | |||||
return &driver; | |||||
} | |||||
static uint8_t keyboard_leds(void) { | |||||
return usb_keyboard_leds; | |||||
} | |||||
static void send_keyboard(report_keyboard_t *report) | |||||
{ | |||||
usb_keyboard_send_report(report); | |||||
} | |||||
static void send_mouse(report_mouse_t *report) | |||||
{ | |||||
#ifdef MOUSE_ENABLE | |||||
usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons); | |||||
#endif | |||||
} | |||||
static void send_system(uint16_t data) | |||||
{ | |||||
#ifdef EXTRAKEY_ENABLE | |||||
usb_extra_system_send(data); | |||||
#endif | |||||
} | |||||
static void send_consumer(uint16_t data) | |||||
{ | |||||
#ifdef EXTRAKEY_ENABLE | |||||
usb_extra_consumer_send(data); | |||||
#endif | |||||
} |
@ -0,0 +1,26 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef PJRC_H | |||||
#define PJRC_H | |||||
#include "host_driver.h" | |||||
host_driver_t *pjrc_driver(void); | |||||
#endif |
@ -0,0 +1,96 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef REPORT_H | |||||
#define REPORT_H | |||||
#include <stdint.h> | |||||
/* report id */ | |||||
#define REPORT_ID_MOUSE 1 | |||||
#define REPORT_ID_SYSTEM 2 | |||||
#define REPORT_ID_CONSUMER 3 | |||||
/* mouse buttons */ | |||||
#define MOUSE_BTN1 (1<<0) | |||||
#define MOUSE_BTN2 (1<<1) | |||||
#define MOUSE_BTN3 (1<<2) | |||||
#define MOUSE_BTN4 (1<<3) | |||||
#define MOUSE_BTN5 (1<<4) | |||||
// Consumer Page(0x0C) | |||||
// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx | |||||
#define AUDIO_MUTE 0x00E2 | |||||
#define AUDIO_VOL_UP 0x00E9 | |||||
#define AUDIO_VOL_DOWN 0x00EA | |||||
#define TRANSPORT_NEXT_TRACK 0x00B5 | |||||
#define TRANSPORT_PREV_TRACK 0x00B6 | |||||
#define TRANSPORT_STOP 0x00B7 | |||||
#define TRANSPORT_PLAY_PAUSE 0x00CD | |||||
#define AL_CC_CONFIG 0x0183 | |||||
#define AL_EMAIL 0x018A | |||||
#define AL_CALCULATOR 0x0192 | |||||
#define AL_LOCAL_BROWSER 0x0194 | |||||
#define AC_SEARCH 0x0221 | |||||
#define AC_HOME 0x0223 | |||||
#define AC_BACK 0x0224 | |||||
#define AC_FORWARD 0x0225 | |||||
#define AC_STOP 0x0226 | |||||
#define AC_REFRESH 0x0227 | |||||
#define AC_BOOKMARKS 0x022A | |||||
// supplement for Bluegiga iWRAP HID(not supported by Windows?) | |||||
#define AL_LOCK 0x019E | |||||
#define TRANSPORT_RECORD 0x00B2 | |||||
#define TRANSPORT_REWIND 0x00B4 | |||||
#define TRANSPORT_EJECT 0x00B8 | |||||
#define AC_MINIMIZE 0x0206 | |||||
// Generic Desktop Page(0x01) | |||||
#define SYSTEM_POWER_DOWN 0x0081 | |||||
#define SYSTEM_SLEEP 0x0082 | |||||
#define SYSTEM_WAKE_UP 0x0083 | |||||
// key report size(NKRO or boot mode) | |||||
#if defined(HOST_PJRC) | |||||
# include "usb.h" | |||||
# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS | |||||
# define REPORT_KEYS KBD2_REPORT_KEYS | |||||
# else | |||||
# define REPORT_KEYS KBD_REPORT_KEYS | |||||
# endif | |||||
#else | |||||
# define REPORT_KEYS 6 | |||||
#endif | |||||
typedef struct { | |||||
uint8_t mods; | |||||
uint8_t rserved; | |||||
uint8_t keys[REPORT_KEYS]; | |||||
} report_keyboard_t; | |||||
typedef struct { | |||||
uint8_t report_id; | |||||
uint8_t buttons; | |||||
int8_t x; | |||||
int8_t y; | |||||
int8_t v; | |||||
int8_t h; | |||||
} report_mouse_t; | |||||
#endif |
@ -0,0 +1,25 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "uart.h" | |||||
#include "sendchar.h" | |||||
int8_t sendchar(uint8_t c) | |||||
{ | |||||
uart_putchar(c); | |||||
return 0; | |||||
} |
@ -0,0 +1,129 @@ | |||||
// TODO: Teensy support(ATMega32u4/AT90USB128) | |||||
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako | |||||
/* UART Example for Teensy USB Development Board | |||||
* http://www.pjrc.com/teensy/ | |||||
* Copyright (c) 2009 PJRC.COM, LLC | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to deal | |||||
* in the Software without restriction, including without limitation the rights | |||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
* copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | |||||
* all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
* THE SOFTWARE. | |||||
*/ | |||||
// Version 1.0: Initial Release | |||||
// Version 1.1: Add support for Teensy 2.0, minor optimizations | |||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | |||||
#include "uart.h" | |||||
// These buffers may be any size from 2 to 256 bytes. | |||||
#define RX_BUFFER_SIZE 64 | |||||
#define TX_BUFFER_SIZE 40 | |||||
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; | |||||
static volatile uint8_t tx_buffer_head; | |||||
static volatile uint8_t tx_buffer_tail; | |||||
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; | |||||
static volatile uint8_t rx_buffer_head; | |||||
static volatile uint8_t rx_buffer_tail; | |||||
// Initialize the UART | |||||
void uart_init(uint32_t baud) | |||||
{ | |||||
cli(); | |||||
UBRR0 = (F_CPU / 4 / baud - 1) / 2; | |||||
UCSR0A = (1<<U2X0); | |||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); | |||||
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); | |||||
tx_buffer_head = tx_buffer_tail = 0; | |||||
rx_buffer_head = rx_buffer_tail = 0; | |||||
sei(); | |||||
} | |||||
// Transmit a byte | |||||
void uart_putchar(uint8_t c) | |||||
{ | |||||
uint8_t i; | |||||
i = tx_buffer_head + 1; | |||||
if (i >= TX_BUFFER_SIZE) i = 0; | |||||
while (tx_buffer_tail == i) ; // wait until space in buffer | |||||
//cli(); | |||||
tx_buffer[i] = c; | |||||
tx_buffer_head = i; | |||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0); | |||||
//sei(); | |||||
} | |||||
// Receive a byte | |||||
uint8_t uart_getchar(void) | |||||
{ | |||||
uint8_t c, i; | |||||
while (rx_buffer_head == rx_buffer_tail) ; // wait for character | |||||
i = rx_buffer_tail + 1; | |||||
if (i >= RX_BUFFER_SIZE) i = 0; | |||||
c = rx_buffer[i]; | |||||
rx_buffer_tail = i; | |||||
return c; | |||||
} | |||||
// Return the number of bytes waiting in the receive buffer. | |||||
// Call this before uart_getchar() to check if it will need | |||||
// to wait for a byte to arrive. | |||||
uint8_t uart_available(void) | |||||
{ | |||||
uint8_t head, tail; | |||||
head = rx_buffer_head; | |||||
tail = rx_buffer_tail; | |||||
if (head >= tail) return head - tail; | |||||
return RX_BUFFER_SIZE + head - tail; | |||||
} | |||||
// Transmit Interrupt | |||||
ISR(USART_UDRE_vect) | |||||
{ | |||||
uint8_t i; | |||||
if (tx_buffer_head == tx_buffer_tail) { | |||||
// buffer is empty, disable transmit interrupt | |||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); | |||||
} else { | |||||
i = tx_buffer_tail + 1; | |||||
if (i >= TX_BUFFER_SIZE) i = 0; | |||||
UDR0 = tx_buffer[i]; | |||||
tx_buffer_tail = i; | |||||
} | |||||
} | |||||
// Receive Interrupt | |||||
ISR(USART_RX_vect) | |||||
{ | |||||
uint8_t c, i; | |||||
c = UDR0; | |||||
i = rx_buffer_head + 1; | |||||
if (i >= RX_BUFFER_SIZE) i = 0; | |||||
if (i != rx_buffer_tail) { | |||||
rx_buffer[i] = c; | |||||
rx_buffer_head = i; | |||||
} | |||||
} | |||||
@ -0,0 +1,11 @@ | |||||
#ifndef _uart_included_h_ | |||||
#define _uart_included_h_ | |||||
#include <stdint.h> | |||||
void uart_init(uint32_t baud); | |||||
void uart_putchar(uint8_t c); | |||||
uint8_t uart_getchar(void); | |||||
uint8_t uart_available(void); | |||||
#endif |
@ -0,0 +1,17 @@ | |||||
OPT_DEFS += -DHOST_VUSB | |||||
SRC += vusb.c \ | |||||
usbdrv.c \ | |||||
usbdrvasm.S \ | |||||
oddebug.c | |||||
ifdef NO_UART | |||||
SRC += sendchar_null.c | |||||
else | |||||
SRC += sendchar_uart.c \ | |||||
uart.c | |||||
endif | |||||
# Search Path | |||||
VPATH += $(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv |
@ -0,0 +1,99 @@ | |||||
/* Name: main.c | |||||
* Project: hid-mouse, a very simple HID example | |||||
* Author: Christian Starkjohann | |||||
* Creation Date: 2008-04-07 | |||||
* Tabsize: 4 | |||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH | |||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | |||||
* This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <avr/interrupt.h> | |||||
#include <avr/wdt.h> | |||||
#include <avr/sleep.h> | |||||
#include <util/delay.h> | |||||
#include "usbdrv.h" | |||||
#include "oddebug.h" | |||||
#include "vusb.h" | |||||
#include "keyboard.h" | |||||
#include "host.h" | |||||
#include "timer.h" | |||||
#include "uart.h" | |||||
#include "debug.h" | |||||
#define UART_BAUD_RATE 115200 | |||||
/* This is from main.c of USBaspLoader */ | |||||
static void initForUsbConnectivity(void) | |||||
{ | |||||
uint8_t i = 0; | |||||
usbInit(); | |||||
/* enforce USB re-enumerate: */ | |||||
usbDeviceDisconnect(); /* do this while interrupts are disabled */ | |||||
while(--i){ /* fake USB disconnect for > 250 ms */ | |||||
wdt_reset(); | |||||
_delay_ms(1); | |||||
} | |||||
usbDeviceConnect(); | |||||
sei(); | |||||
} | |||||
int main(void) | |||||
{ | |||||
bool suspended = false; | |||||
#if USB_COUNT_SOF | |||||
uint16_t last_timer = timer_read(); | |||||
#endif | |||||
CLKPR = 0x80, CLKPR = 0; | |||||
#ifndef PS2_USE_USART | |||||
uart_init(UART_BAUD_RATE); | |||||
#endif | |||||
debug_enable = true; | |||||
print_enable = true; | |||||
debug("keyboard_init()\n"); | |||||
keyboard_init(); | |||||
host_set_driver(vusb_driver()); | |||||
debug("initForUsbConnectivity()\n"); | |||||
initForUsbConnectivity(); | |||||
debug("main loop\n"); | |||||
while (1) { | |||||
#if USB_COUNT_SOF | |||||
if (usbSofCount != 0) { | |||||
suspended = false; | |||||
usbSofCount = 0; | |||||
last_timer = timer_read(); | |||||
} else { | |||||
// Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) | |||||
if (timer_elapsed(last_timer) > 5) { | |||||
suspended = true; | |||||
/* | |||||
uart_putchar('S'); | |||||
_delay_ms(1); | |||||
cli(); | |||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |||||
sleep_enable(); | |||||
sleep_bod_disable(); | |||||
sei(); | |||||
sleep_cpu(); | |||||
sleep_disable(); | |||||
_delay_ms(10); | |||||
uart_putchar('W'); | |||||
*/ | |||||
} | |||||
} | |||||
#endif | |||||
if (!suspended) | |||||
usbPoll(); | |||||
keyboard_proc(); | |||||
if (!suspended) | |||||
vusb_transfer_keyboard(); | |||||
} | |||||
} |
@ -0,0 +1,27 @@ | |||||
/* | |||||
Copyright 2011 Jun Wako <wakojun@gmail.com> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef VUSB_H | |||||
#define VUSB_H | |||||
#include "host_driver.h" | |||||
host_driver_t *vusb_driver(void); | |||||
void vusb_transfer_keyboard(void); | |||||
#endif |