mirror of
				https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
				synced 2025-10-30 18:55:21 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			594 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			594 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //////////////////////////////////////////////////////////////////////////////
 | |
| //                                                                          //
 | |
| //                  _   _  ___  ____                                        //
 | |
| //                 | | | ||_ _||  _ \    ___  _ __   _ __                   //
 | |
| //                 | |_| | | | | | | |  / __|| '_ \ | '_ \                  //
 | |
| //                 |  _  | | | | |_| |_| (__ | |_) || |_) |                 //
 | |
| //                 |_| |_||___||____/(_)\___|| .__/ | .__/                  //
 | |
| //                                           |_|    |_|                     //
 | |
| //                                                                          //
 | |
| //////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| /* Copyright (c) 2011, Peter Barrett
 | |
| **
 | |
| ** 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.
 | |
| */
 | |
| 
 | |
| /////////////////////////////////////////////////////////////////////////////////
 | |
| // XMEGA NOTES:
 | |
| //
 | |
| // a) it appears that, at one time at least, this was intended to be overridden
 | |
| //    by user code, hence the use of 'WEAK' all over the place;
 | |
| // b) This API is *VERY* 'tricky' in that it's tied in heavily with the atmega
 | |
| //    USB implementation and (in some cases) does 'magic things' that are not
 | |
| //    apparently obvious to someone trying to port it to another processor
 | |
| //    (for an example see original use of CDC_GetInterface - lame!)
 | |
| // c) Given the fact that it's (in my view) POORLY WRITTEN, it deserves a makeover.
 | |
| // d) K&R style is hard to read.  I won't use it.  Hard tabs are evil.  Same.
 | |
| //
 | |
| /////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #include "Platform.h"
 | |
| #include "USBAPI.h"
 | |
| #include "USBDesc.h"
 | |
| 
 | |
| #if defined(USBCON)
 | |
| #ifdef HID_ENABLED
 | |
| 
 | |
| #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 | |
| #define PROGMEM_ORIG PROGMEM
 | |
| #else // PROGMEM workaround
 | |
| 
 | |
| // to avoid the bogus "initialized variables" warning
 | |
| #ifdef PROGMEM
 | |
| #undef PROGMEM
 | |
| #endif // PROGMEM re-define
 | |
| 
 | |
| #define PROGMEM __attribute__((section(".progmem.hid")))
 | |
| #define PROGMEM_ORIG __attribute__((__progmem__))
 | |
| 
 | |
| #endif // check for GNUC >= or < 4.6
 | |
| 
 | |
| 
 | |
| //#define RAWHID_ENABLED
 | |
| 
 | |
| //  Singletons for mouse and keyboard
 | |
| 
 | |
| Mouse_ Mouse;
 | |
| Keyboard_ Keyboard;
 | |
| 
 | |
| //================================================================================
 | |
| //================================================================================
 | |
| 
 | |
| //  HID report descriptor
 | |
| 
 | |
| #define LSB(_x) ((_x) & 0xFF)
 | |
| #define MSB(_x) ((_x) >> 8)
 | |
| 
 | |
| #define RAWHID_USAGE_PAGE  0xFFC0
 | |
| #define RAWHID_USAGE    0x0C00
 | |
| #define RAWHID_TX_SIZE 64
 | |
| #define RAWHID_RX_SIZE 64
 | |
| 
 | |
| const u8 _hidReportDescriptor[] PROGMEM =
 | |
| {
 | |
|   //  Mouse
 | |
|     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 54
 | |
|     0x09, 0x02,                    // USAGE (Mouse)
 | |
|     0xa1, 0x01,                    // COLLECTION (Application)
 | |
|     0x09, 0x01,                    //   USAGE (Pointer)
 | |
|     0xa1, 0x00,                    //   COLLECTION (Physical)
 | |
|     0x85, 0x01,                    //     REPORT_ID (1)
 | |
|     0x05, 0x09,                    //     USAGE_PAGE (Button)
 | |
|     0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
 | |
|     0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
 | |
|     0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
 | |
|     0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
 | |
|     0x95, 0x03,                    //     REPORT_COUNT (3)
 | |
|     0x75, 0x01,                    //     REPORT_SIZE (1)
 | |
|     0x81, 0x02,                    //     INPUT (Data,Var,Abs)
 | |
|     0x95, 0x01,                    //     REPORT_COUNT (1)
 | |
|     0x75, 0x05,                    //     REPORT_SIZE (5)
 | |
|     0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
 | |
|     0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
 | |
|     0x09, 0x30,                    //     USAGE (X)
 | |
|     0x09, 0x31,                    //     USAGE (Y)
 | |
|     0x09, 0x38,                    //     USAGE (Wheel)
 | |
|     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
 | |
|     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
 | |
|     0x75, 0x08,                    //     REPORT_SIZE (8)
 | |
|     0x95, 0x03,                    //     REPORT_COUNT (3)
 | |
|     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
 | |
|     0xc0,                          //   END_COLLECTION
 | |
|     0xc0,                          // END_COLLECTION
 | |
| 
 | |
|   //  Keyboard
 | |
|     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 47
 | |
|     0x09, 0x06,                    // USAGE (Keyboard)
 | |
|     0xa1, 0x01,                    // COLLECTION (Application)
 | |
|     0x85, 0x02,                    //   REPORT_ID (2)
 | |
|     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
 | |
| 
 | |
|   0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
 | |
|     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
 | |
|     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
 | |
|     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
 | |
|     0x75, 0x01,                    //   REPORT_SIZE (1)
 | |
| 
 | |
|   0x95, 0x08,                    //   REPORT_COUNT (8)
 | |
|     0x81, 0x02,                    //   INPUT (Data,Var,Abs)
 | |
|     0x95, 0x01,                    //   REPORT_COUNT (1)
 | |
|     0x75, 0x08,                    //   REPORT_SIZE (8)
 | |
|     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
 | |
| 
 | |
|   0x95, 0x06,                    //   REPORT_COUNT (6)
 | |
|     0x75, 0x08,                    //   REPORT_SIZE (8)
 | |
|     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
 | |
|     0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
 | |
|     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
 | |
| 
 | |
|   0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
 | |
|     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
 | |
|     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
 | |
|     0xc0,                          // END_COLLECTION
 | |
| 
 | |
| #ifdef RAWHID_ENABLED
 | |
|   //  RAW HID
 | |
|   0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),  // 30
 | |
|   0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
 | |
| 
 | |
|   0xA1, 0x01,        // Collection 0x01
 | |
|     0x85, 0x03,             // REPORT_ID (3)
 | |
|   0x75, 0x08,        // report size = 8 bits
 | |
|   0x15, 0x00,        // logical minimum = 0
 | |
|   0x26, 0xFF, 0x00,    // logical maximum = 255
 | |
| 
 | |
|   0x95, 64,        // report count TX
 | |
|   0x09, 0x01,        // usage
 | |
|   0x81, 0x02,        // Input (array)
 | |
| 
 | |
|   0x95, 64,        // report count RX
 | |
|   0x09, 0x02,        // usage
 | |
|   0x91, 0x02,        // Output (array)
 | |
|   0xC0          // end collection
 | |
| #endif
 | |
| };
 | |
| 
 | |
| 
 | |
| const HIDDescriptor _hidInterface PROGMEM =
 | |
| {
 | |
|   D_INTERFACE(HID_INTERFACE,1,3,0,0),
 | |
|   D_HIDREPORT(sizeof(_hidReportDescriptor)),
 | |
|   D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
 | |
| };
 | |
| 
 | |
| //================================================================================
 | |
| //================================================================================
 | |
| //  Driver
 | |
| 
 | |
| u8 _hid_protocol = 1;
 | |
| u8 _hid_idle = 1;
 | |
| 
 | |
| #define WEAK __attribute__ ((weak))
 | |
| 
 | |
| int WEAK HID_GetNumInterfaces(void)
 | |
| {
 | |
|   return 1; // always 1
 | |
| }
 | |
| 
 | |
| int WEAK HID_GetInterfaceDataLength(void)
 | |
| {
 | |
|   return sizeof(_hidInterface);
 | |
| }
 | |
| 
 | |
| int WEAK HID_SendInterfaceData(void)
 | |
| {
 | |
|   return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface));
 | |
| }
 | |
| 
 | |
| int WEAK HID_GetDescriptor(int i)
 | |
| {
 | |
|   // NOTE:  'i' is the max size for the request.  Should I pay attention to it?
 | |
| 
 | |
|   return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
 | |
| }
 | |
| 
 | |
| void WEAK HID_SendReport(u8 id, const void* data, int len)
 | |
| {
 | |
|   USB_Send(HID_TX, &id, 1, 0);
 | |
|   USB_Send(HID_TX,data,len, 1);
 | |
| }
 | |
| 
 | |
| bool WEAK HID_Setup(Setup& setup)
 | |
| {
 | |
|   u8 r = setup.bRequest;
 | |
|   u8 requestType = setup.bmRequestType;
 | |
| 
 | |
|   if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
 | |
|   {
 | |
|     if (HID_GET_REPORT == r)
 | |
|     {
 | |
|       //HID_GetReport();
 | |
|       return true;
 | |
|     }
 | |
|     if (HID_GET_PROTOCOL == r)
 | |
|     {
 | |
|       //Send8(_hid_protocol);  // TODO
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
 | |
|   {
 | |
|     if (HID_SET_PROTOCOL == r)
 | |
|     {
 | |
|       _hid_protocol = setup.wValueL;
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|     if (HID_SET_IDLE == r)
 | |
|     {
 | |
|       _hid_idle = setup.wValueL;
 | |
|       return true;
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| //================================================================================
 | |
| //================================================================================
 | |
| //  Mouse
 | |
| 
 | |
| Mouse_::Mouse_(void) : _buttons(0)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Mouse_::begin(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Mouse_::end(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Mouse_::click(uint8_t b)
 | |
| {
 | |
|   _buttons = b;
 | |
|   move(0,0,0);
 | |
|   _buttons = 0;
 | |
|   move(0,0,0);
 | |
| }
 | |
| 
 | |
| void Mouse_::move(signed char x, signed char y, signed char wheel)
 | |
| {
 | |
|   u8 m[4];
 | |
|   m[0] = _buttons;
 | |
|   m[1] = x;
 | |
|   m[2] = y;
 | |
|   m[3] = wheel;
 | |
|   HID_SendReport(1,m,4);
 | |
| }
 | |
| 
 | |
| void Mouse_::buttons(uint8_t b)
 | |
| {
 | |
|   if (b != _buttons)
 | |
|   {
 | |
|     _buttons = b;
 | |
|     move(0,0,0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Mouse_::press(uint8_t b)
 | |
| {
 | |
|   buttons(_buttons | b);
 | |
| }
 | |
| 
 | |
| void Mouse_::release(uint8_t b)
 | |
| {
 | |
|   buttons(_buttons & ~b);
 | |
| }
 | |
| 
 | |
| bool Mouse_::isPressed(uint8_t b)
 | |
| {
 | |
|   if ((b & _buttons) > 0)
 | |
|   {
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| //================================================================================
 | |
| //================================================================================
 | |
| //  Keyboard
 | |
| 
 | |
| Keyboard_::Keyboard_(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Keyboard_::begin(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Keyboard_::end(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void Keyboard_::sendReport(KeyReport* keys)
 | |
| {
 | |
|   HID_SendReport(2,keys,sizeof(KeyReport));
 | |
| }
 | |
| 
 | |
| extern
 | |
| const uint8_t _asciimap[128] PROGMEM;
 | |
| 
 | |
| #define SHIFT 0x80
 | |
| const uint8_t _asciimap[128] =
 | |
| {
 | |
|   0x00,             // NUL
 | |
|   0x00,             // SOH
 | |
|   0x00,             // STX
 | |
|   0x00,             // ETX
 | |
|   0x00,             // EOT
 | |
|   0x00,             // ENQ
 | |
|   0x00,             // ACK
 | |
|   0x00,             // BEL
 | |
|   0x2a,      // BS  Backspace
 | |
|   0x2b,      // TAB  Tab
 | |
|   0x28,      // LF  Enter
 | |
|   0x00,             // VT
 | |
|   0x00,             // FF
 | |
|   0x00,             // CR
 | |
|   0x00,             // SO
 | |
|   0x00,             // SI
 | |
|   0x00,             // DEL
 | |
|   0x00,             // DC1
 | |
|   0x00,             // DC2
 | |
|   0x00,             // DC3
 | |
|   0x00,             // DC4
 | |
|   0x00,             // NAK
 | |
|   0x00,             // SYN
 | |
|   0x00,             // ETB
 | |
|   0x00,             // CAN
 | |
|   0x00,             // EM
 | |
|   0x00,             // SUB
 | |
|   0x00,             // ESC
 | |
|   0x00,             // FS
 | |
|   0x00,             // GS
 | |
|   0x00,             // RS
 | |
|   0x00,             // US
 | |
| 
 | |
|   0x2c,       //  ' '
 | |
|   0x1e|SHIFT,     // !
 | |
|   0x34|SHIFT,     // "
 | |
|   0x20|SHIFT,    // #
 | |
|   0x21|SHIFT,    // $
 | |
|   0x22|SHIFT,    // %
 | |
|   0x24|SHIFT,    // &
 | |
|   0x34,          // '
 | |
|   0x26|SHIFT,    // (
 | |
|   0x27|SHIFT,    // )
 | |
|   0x25|SHIFT,    // *
 | |
|   0x2e|SHIFT,    // +
 | |
|   0x36,          // ,
 | |
|   0x2d,          // -
 | |
|   0x37,          // .
 | |
|   0x38,          // /
 | |
|   0x27,          // 0
 | |
|   0x1e,          // 1
 | |
|   0x1f,          // 2
 | |
|   0x20,          // 3
 | |
|   0x21,          // 4
 | |
|   0x22,          // 5
 | |
|   0x23,          // 6
 | |
|   0x24,          // 7
 | |
|   0x25,          // 8
 | |
|   0x26,          // 9
 | |
|   0x33|SHIFT,      // :
 | |
|   0x33,          // ;
 | |
|   0x36|SHIFT,      // <
 | |
|   0x2e,          // =
 | |
|   0x37|SHIFT,      // >
 | |
|   0x38|SHIFT,      // ?
 | |
|   0x1f|SHIFT,      // @
 | |
|   0x04|SHIFT,      // A
 | |
|   0x05|SHIFT,      // B
 | |
|   0x06|SHIFT,      // C
 | |
|   0x07|SHIFT,      // D
 | |
|   0x08|SHIFT,      // E
 | |
|   0x09|SHIFT,      // F
 | |
|   0x0a|SHIFT,      // G
 | |
|   0x0b|SHIFT,      // H
 | |
|   0x0c|SHIFT,      // I
 | |
|   0x0d|SHIFT,      // J
 | |
|   0x0e|SHIFT,      // K
 | |
|   0x0f|SHIFT,      // L
 | |
|   0x10|SHIFT,      // M
 | |
|   0x11|SHIFT,      // N
 | |
|   0x12|SHIFT,      // O
 | |
|   0x13|SHIFT,      // P
 | |
|   0x14|SHIFT,      // Q
 | |
|   0x15|SHIFT,      // R
 | |
|   0x16|SHIFT,      // S
 | |
|   0x17|SHIFT,      // T
 | |
|   0x18|SHIFT,      // U
 | |
|   0x19|SHIFT,      // V
 | |
|   0x1a|SHIFT,      // W
 | |
|   0x1b|SHIFT,      // X
 | |
|   0x1c|SHIFT,      // Y
 | |
|   0x1d|SHIFT,      // Z
 | |
|   0x2f,          // [
 | |
|   0x31,          // bslash
 | |
|   0x30,          // ]
 | |
|   0x23|SHIFT,    // ^
 | |
|   0x2d|SHIFT,    // _
 | |
|   0x35,          // `
 | |
|   0x04,          // a
 | |
|   0x05,          // b
 | |
|   0x06,          // c
 | |
|   0x07,          // d
 | |
|   0x08,          // e
 | |
|   0x09,          // f
 | |
|   0x0a,          // g
 | |
|   0x0b,          // h
 | |
|   0x0c,          // i
 | |
|   0x0d,          // j
 | |
|   0x0e,          // k
 | |
|   0x0f,          // l
 | |
|   0x10,          // m
 | |
|   0x11,          // n
 | |
|   0x12,          // o
 | |
|   0x13,          // p
 | |
|   0x14,          // q
 | |
|   0x15,          // r
 | |
|   0x16,          // s
 | |
|   0x17,          // t
 | |
|   0x18,          // u
 | |
|   0x19,          // v
 | |
|   0x1a,          // w
 | |
|   0x1b,          // x
 | |
|   0x1c,          // y
 | |
|   0x1d,          // z
 | |
|   0x2f|SHIFT,    //
 | |
|   0x31|SHIFT,    // |
 | |
|   0x30|SHIFT,    // }
 | |
|   0x35|SHIFT,    // ~
 | |
|   0        // DEL
 | |
| };
 | |
| 
 | |
| uint8_t USBPutChar(uint8_t c);
 | |
| 
 | |
| // press() adds the specified key (printing, non-printing, or modifier)
 | |
| // to the persistent key report and sends the report.  Because of the way
 | |
| // USB HID works, the host acts like the key remains pressed until we
 | |
| // call release(), releaseAll(), or otherwise clear the report and resend.
 | |
| size_t Keyboard_::press(uint8_t k)
 | |
| {
 | |
|   uint8_t i;
 | |
|   if (k >= 136)    // it's a non-printing key (not a modifier)
 | |
|   {
 | |
|     k = k - 136;
 | |
|   }
 | |
|   else if (k >= 128)
 | |
|   {  // it's a modifier key
 | |
|     _keyReport.modifiers |= (1<<(k-128));
 | |
|     k = 0;
 | |
|   }
 | |
|   else             // it's a printing key
 | |
|   {
 | |
|     k = pgm_read_byte(_asciimap + k);
 | |
|     if (!k)
 | |
|     {
 | |
|       setWriteError();
 | |
|       return 0;
 | |
|     }
 | |
|     if (k & 0x80)  // it's a capital letter or other character reached with shift
 | |
|     {
 | |
|       _keyReport.modifiers |= 0x02;  // the left shift modifier
 | |
|       k &= 0x7F;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Add k to the key report only if it's not already present
 | |
|   // and if there is an empty slot.
 | |
|   if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
 | |
|     _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
 | |
|     _keyReport.keys[4] != k && _keyReport.keys[5] != k)
 | |
|   {
 | |
|     for (i=0; i<6; i++)
 | |
|     {
 | |
|       if (_keyReport.keys[i] == 0x00)
 | |
|       {
 | |
|         _keyReport.keys[i] = k;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     if (i == 6)
 | |
|     {
 | |
|       setWriteError();
 | |
|       return 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   sendReport(&_keyReport);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| // release() takes the specified key out of the persistent key report and
 | |
| // sends the report.  This tells the OS the key is no longer pressed and that
 | |
| // it shouldn't be repeated any more.
 | |
| size_t Keyboard_::release(uint8_t k)
 | |
| {
 | |
|   uint8_t i;
 | |
|   if (k >= 136)
 | |
|   {      // it's a non-printing key (not a modifier)
 | |
|     k = k - 136;
 | |
|   }
 | |
|   else if (k >= 128)
 | |
|   {  // it's a modifier key
 | |
|     _keyReport.modifiers &= ~(1<<(k-128));
 | |
|     k = 0;
 | |
|   }
 | |
|   else
 | |
|   {        // it's a printing key
 | |
|     k = pgm_read_byte(_asciimap + k);
 | |
|     if (!k)
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
|     if (k & 0x80)
 | |
|     {              // it's a capital letter or other character reached with shift
 | |
|       _keyReport.modifiers &= ~(0x02);  // the left shift modifier
 | |
|       k &= 0x7F;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Test the key report to see if k is present.  Clear it if it exists.
 | |
|   // Check all positions in case the key is present more than once (which it shouldn't be)
 | |
|   for (i=0; i<6; i++)
 | |
|   {
 | |
|     if (0 != k && _keyReport.keys[i] == k)
 | |
|     {
 | |
|       _keyReport.keys[i] = 0x00;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   sendReport(&_keyReport);
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| void Keyboard_::releaseAll(void)
 | |
| {
 | |
|   _keyReport.keys[0] = 0;
 | |
|   _keyReport.keys[1] = 0;
 | |
|   _keyReport.keys[2] = 0;
 | |
|   _keyReport.keys[3] = 0;
 | |
|   _keyReport.keys[4] = 0;
 | |
|   _keyReport.keys[5] = 0;
 | |
|   _keyReport.modifiers = 0;
 | |
|   sendReport(&_keyReport);
 | |
| }
 | |
| 
 | |
| size_t Keyboard_::write(uint8_t c)
 | |
| {
 | |
|   uint8_t p = press(c);    // Keydown
 | |
|   /*uint8_t r =*/ release(c);    // Keyup
 | |
|   return (p);          // just return the result of press() since release() almost always returns 1
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #endif /* if defined(USBCON) */
 | |
| 
 |