/* Copyright 2011 Jun Wako 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 . */ /* 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 #include #include #include #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<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 }