]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Output/pjrcUSB/arm/usb_keyboard.c
Fixed Linux NKRO bitmap bug.
[kiibohd-controller.git] / Output / pjrcUSB / arm / usb_keyboard.c
1 /* Teensyduino Core Library
2  * http://www.pjrc.com/teensy/
3  * Copyright (c) 2013 PJRC.COM, LLC.
4  * Modifications by Jacob Alexander 2013-2014
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * 1. The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * 2. If the Software is incorporated into a build system that allows
18  * selection among a list of target devices, then similar target
19  * devices manufactured by PJRC.COM must be included in the list of
20  * target devices and selectable in the same manner.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  */
31
32 // ----- Includes -----
33
34 // Compiler Includes
35 #include <string.h> // for memcpy()
36
37 // Project Includes
38 #include <Lib/OutputLib.h>
39 #include <print.h>
40
41 // Local Includes
42 #include "usb_dev.h"
43 #include "usb_keyboard.h"
44
45
46
47 // ----- Defines -----
48
49 // Maximum number of transmit packets to queue so we don't starve other endpoints for memory
50 #define TX_PACKET_LIMIT 4
51
52 // When the PC isn't listening, how long do we wait before discarding data?
53 #define TX_TIMEOUT_MSEC 50
54
55 #if F_CPU == 96000000
56   #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
57 #elif F_CPU == 48000000
58   #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
59 #elif F_CPU == 24000000
60   #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
61 #endif
62
63
64
65 // ----- Variables -----
66
67 static uint8_t transmit_previous_timeout = 0;
68
69
70
71 // ----- Functions -----
72
73 // send the contents of keyboard_keys and keyboard_modifier_keys
74 void usb_keyboard_send()
75 {
76         uint32_t wait_count = 0;
77         usb_packet_t *tx_packet;
78
79         // Wait till ready
80         while ( 1 )
81         {
82                 if ( !usb_configuration )
83                 {
84                         erro_print("USB not configured...");
85                         return;
86                 }
87
88                 if ( USBKeys_Protocol == 0 ) // Boot Mode
89                 {
90                         if ( usb_tx_packet_count( NKRO_KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT )
91                         {
92                                 tx_packet = usb_malloc();
93                                 if ( tx_packet )
94                                         break;
95                         }
96                 }
97                 else if ( USBKeys_Protocol == 1 ) // NKRO Mode
98                 {
99                         if ( usb_tx_packet_count( KEYBOARD_ENDPOINT ) < TX_PACKET_LIMIT )
100                         {
101                                 tx_packet = usb_malloc();
102                                 if ( tx_packet )
103                                         break;
104                         }
105                 }
106
107                 if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout )
108                 {
109                         transmit_previous_timeout = 1;
110                         warn_print("USB Transmit Timeout...");
111                         return;
112                 }
113                 yield();
114         }
115
116         // Pointer to USB tx packet buffer
117         uint8_t *tx_buf = tx_packet->buf;
118
119         switch ( USBKeys_Protocol )
120         {
121         // Send boot keyboard interrupt packet(s)
122         case 0:
123                 // Boot Mode
124                 *tx_buf++ = USBKeys_Modifiers;
125                 *tx_buf++ = 0;
126                 memcpy( tx_buf, USBKeys_Keys, USB_BOOT_MAX_KEYS );
127                 tx_packet->len = 8;
128
129                 // Send USB Packet
130                 usb_tx( KEYBOARD_ENDPOINT, tx_packet );
131                 USBKeys_Changed = USBKeyChangeState_None;
132                 break;
133
134         // Send NKRO keyboard interrupts packet(s)
135         case 1:
136                 // Check modifiers
137                 if ( USBKeys_Changed & USBKeyChangeState_Modifiers )
138                 {
139                         *tx_buf++ = 0x01; // ID
140                         *tx_buf   = USBKeys_Modifiers;
141                         tx_packet->len = 2;
142
143                         // Send USB Packet
144                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
145                         USBKeys_Changed &= ~USBKeyChangeState_Modifiers; // Mark sent
146                 }
147                 // Check main key section
148                 else if ( USBKeys_Changed & USBKeyChangeState_MainKeys )
149                 {
150                         *tx_buf++ = 0x03; // ID
151
152                         // 4-49 (first 6 bytes)
153                         memcpy( tx_buf, USBKeys_Keys, 6 );
154                         tx_packet->len = 7;
155
156                         // Send USB Packet
157                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
158                         USBKeys_Changed &= ~USBKeyChangeState_MainKeys; // Mark sent
159                 }
160                 // Check secondary key section
161                 else if ( USBKeys_Changed & USBKeyChangeState_SecondaryKeys )
162                 {
163                         *tx_buf++ = 0x04; // ID
164
165                         // 51-164 (Middle 15 bytes)
166                         memcpy( tx_buf, USBKeys_Keys + 6, 15 );
167                         tx_packet->len = 16;
168
169                         // Send USB Packet
170                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
171                         USBKeys_Changed &= ~USBKeyChangeState_SecondaryKeys; // Mark sent
172                 }
173                 // Check tertiary key section
174                 else if ( USBKeys_Changed & USBKeyChangeState_TertiaryKeys )
175                 {
176                         *tx_buf++ = 0x05; // ID
177
178                         // 176-221 (last 6 bytes)
179                         memcpy( tx_buf, USBKeys_Keys + 21, 6 );
180                         tx_packet->len = 7;
181
182                         // Send USB Packet
183                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
184                         USBKeys_Changed &= ~USBKeyChangeState_TertiaryKeys; // Mark sent
185                 }
186                 // Check system control keys
187                 else if ( USBKeys_Changed & USBKeyChangeState_System )
188                 {
189                         *tx_buf++ = 0x06; // ID
190                         *tx_buf   = USBKeys_SysCtrl;
191                         tx_packet->len = 2;
192
193                         // Send USB Packet
194                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
195                         USBKeys_Changed &= ~USBKeyChangeState_System; // Mark sent
196                 }
197                 // Check consumer control keys
198                 else if ( USBKeys_Changed & USBKeyChangeState_Consumer )
199                 {
200                         *tx_buf++ = 0x07; // ID
201                         *tx_buf++ = (uint8_t)(USBKeys_ConsCtrl & 0x00FF);
202                         *tx_buf   = (uint8_t)(USBKeys_ConsCtrl >> 8);
203                         tx_packet->len = 3;
204
205                         // Send USB Packet
206                         usb_tx( NKRO_KEYBOARD_ENDPOINT, tx_packet );
207                         USBKeys_Changed &= ~USBKeyChangeState_Consumer; // Mark sent
208                 }
209
210                 break;
211         }
212
213         return;
214 }
215