diff options
| author | skullY <skullydazed@gmail.com> | 2019-08-30 11:19:03 -0700 |
|---|---|---|
| committer | skullydazed <skullydazed@users.noreply.github.com> | 2019-08-30 15:01:52 -0700 |
| commit | b624f32f944acdc59dcb130674c09090c5c404cb (patch) | |
| tree | bc13adbba137d122d9a2c2fb2fafcbb08ac10e25 /tmk_core/protocol/lufa | |
| parent | 61af76a10d00aba185b8338604171de490a13e3b (diff) | |
| download | qmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.tar.gz qmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.zip | |
clang-format changes
Diffstat (limited to 'tmk_core/protocol/lufa')
| -rw-r--r-- | tmk_core/protocol/lufa/adafruit_ble.cpp | 1117 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/adafruit_ble.h | 30 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/bluetooth.c | 20 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/bluetooth.h | 37 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 692 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.h | 20 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/outputselect.c | 9 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/outputselect.h | 14 |
8 files changed, 892 insertions, 1047 deletions
diff --git a/tmk_core/protocol/lufa/adafruit_ble.cpp b/tmk_core/protocol/lufa/adafruit_ble.cpp index 80839731f..71d0936f8 100644 --- a/tmk_core/protocol/lufa/adafruit_ble.cpp +++ b/tmk_core/protocol/lufa/adafruit_ble.cpp | |||
| @@ -15,35 +15,34 @@ | |||
| 15 | // You may define them to something else in your config.h | 15 | // You may define them to something else in your config.h |
| 16 | // if yours is wired up differently. | 16 | // if yours is wired up differently. |
| 17 | #ifndef AdafruitBleResetPin | 17 | #ifndef AdafruitBleResetPin |
| 18 | #define AdafruitBleResetPin D4 | 18 | # define AdafruitBleResetPin D4 |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | #ifndef AdafruitBleCSPin | 21 | #ifndef AdafruitBleCSPin |
| 22 | #define AdafruitBleCSPin B4 | 22 | # define AdafruitBleCSPin B4 |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #ifndef AdafruitBleIRQPin | 25 | #ifndef AdafruitBleIRQPin |
| 26 | #define AdafruitBleIRQPin E6 | 26 | # define AdafruitBleIRQPin E6 |
| 27 | #endif | 27 | #endif |
| 28 | 28 | ||
| 29 | |||
| 30 | #define SAMPLE_BATTERY | 29 | #define SAMPLE_BATTERY |
| 31 | #define ConnectionUpdateInterval 1000 /* milliseconds */ | 30 | #define ConnectionUpdateInterval 1000 /* milliseconds */ |
| 32 | 31 | ||
| 33 | static struct { | 32 | static struct { |
| 34 | bool is_connected; | 33 | bool is_connected; |
| 35 | bool initialized; | 34 | bool initialized; |
| 36 | bool configured; | 35 | bool configured; |
| 37 | 36 | ||
| 38 | #define ProbedEvents 1 | 37 | #define ProbedEvents 1 |
| 39 | #define UsingEvents 2 | 38 | #define UsingEvents 2 |
| 40 | bool event_flags; | 39 | bool event_flags; |
| 41 | 40 | ||
| 42 | #ifdef SAMPLE_BATTERY | 41 | #ifdef SAMPLE_BATTERY |
| 43 | uint16_t last_battery_update; | 42 | uint16_t last_battery_update; |
| 44 | uint32_t vbat; | 43 | uint32_t vbat; |
| 45 | #endif | 44 | #endif |
| 46 | uint16_t last_connection_update; | 45 | uint16_t last_connection_update; |
| 47 | } state; | 46 | } state; |
| 48 | 47 | ||
| 49 | // Commands are encoded using SDEP and sent via SPI | 48 | // Commands are encoded using SDEP and sent via SPI |
| @@ -51,14 +50,14 @@ static struct { | |||
| 51 | 50 | ||
| 52 | #define SdepMaxPayload 16 | 51 | #define SdepMaxPayload 16 |
| 53 | struct sdep_msg { | 52 | struct sdep_msg { |
| 54 | uint8_t type; | 53 | uint8_t type; |
| 55 | uint8_t cmd_low; | 54 | uint8_t cmd_low; |
| 56 | uint8_t cmd_high; | 55 | uint8_t cmd_high; |
| 57 | struct __attribute__((packed)) { | 56 | struct __attribute__((packed)) { |
| 58 | uint8_t len:7; | 57 | uint8_t len : 7; |
| 59 | uint8_t more:1; | 58 | uint8_t more : 1; |
| 60 | }; | 59 | }; |
| 61 | uint8_t payload[SdepMaxPayload]; | 60 | uint8_t payload[SdepMaxPayload]; |
| 62 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
| 63 | 62 | ||
| 64 | // The recv latency is relatively high, so when we're hammering keys quickly, | 63 | // The recv latency is relatively high, so when we're hammering keys quickly, |
| @@ -68,28 +67,28 @@ struct sdep_msg { | |||
| 68 | // information here. | 67 | // information here. |
| 69 | 68 | ||
| 70 | enum queue_type { | 69 | enum queue_type { |
| 71 | QTKeyReport, // 1-byte modifier + 6-byte key report | 70 | QTKeyReport, // 1-byte modifier + 6-byte key report |
| 72 | QTConsumer, // 16-bit key code | 71 | QTConsumer, // 16-bit key code |
| 73 | #ifdef MOUSE_ENABLE | 72 | #ifdef MOUSE_ENABLE |
| 74 | QTMouseMove, // 4-byte mouse report | 73 | QTMouseMove, // 4-byte mouse report |
| 75 | #endif | 74 | #endif |
| 76 | }; | 75 | }; |
| 77 | 76 | ||
| 78 | struct queue_item { | 77 | struct queue_item { |
| 79 | enum queue_type queue_type; | 78 | enum queue_type queue_type; |
| 80 | uint16_t added; | 79 | uint16_t added; |
| 81 | union __attribute__((packed)) { | 80 | union __attribute__((packed)) { |
| 82 | struct __attribute__((packed)) { | 81 | struct __attribute__((packed)) { |
| 83 | uint8_t modifier; | 82 | uint8_t modifier; |
| 84 | uint8_t keys[6]; | 83 | uint8_t keys[6]; |
| 85 | } key; | 84 | } key; |
| 86 | 85 | ||
| 87 | uint16_t consumer; | 86 | uint16_t consumer; |
| 88 | struct __attribute__((packed)) { | 87 | struct __attribute__((packed)) { |
| 89 | int8_t x, y, scroll, pan; | 88 | int8_t x, y, scroll, pan; |
| 90 | uint8_t buttons; | 89 | uint8_t buttons; |
| 91 | } mousemove; | 90 | } mousemove; |
| 92 | }; | 91 | }; |
| 93 | }; | 92 | }; |
| 94 | 93 | ||
| 95 | // Items that we wish to send | 94 | // Items that we wish to send |
| @@ -102,108 +101,104 @@ static RingBuffer<uint16_t, 2> resp_buf; | |||
| 102 | static bool process_queue_item(struct queue_item *item, uint16_t timeout); | 101 | static bool process_queue_item(struct queue_item *item, uint16_t timeout); |
| 103 | 102 | ||
| 104 | enum sdep_type { | 103 | enum sdep_type { |
| 105 | SdepCommand = 0x10, | 104 | SdepCommand = 0x10, |
| 106 | SdepResponse = 0x20, | 105 | SdepResponse = 0x20, |
| 107 | SdepAlert = 0x40, | 106 | SdepAlert = 0x40, |
| 108 | SdepError = 0x80, | 107 | SdepError = 0x80, |
| 109 | SdepSlaveNotReady = 0xfe, // Try again later | 108 | SdepSlaveNotReady = 0xfe, // Try again later |
| 110 | SdepSlaveOverflow = 0xff, // You read more data than is available | 109 | SdepSlaveOverflow = 0xff, // You read more data than is available |
| 111 | }; | 110 | }; |
| 112 | 111 | ||
| 113 | enum ble_cmd { | 112 | enum ble_cmd { |
| 114 | BleInitialize = 0xbeef, | 113 | BleInitialize = 0xbeef, |
| 115 | BleAtWrapper = 0x0a00, | 114 | BleAtWrapper = 0x0a00, |
| 116 | BleUartTx = 0x0a01, | 115 | BleUartTx = 0x0a01, |
| 117 | BleUartRx = 0x0a02, | 116 | BleUartRx = 0x0a02, |
| 118 | }; | 117 | }; |
| 119 | 118 | ||
| 120 | enum ble_system_event_bits { | 119 | enum ble_system_event_bits { |
| 121 | BleSystemConnected = 0, | 120 | BleSystemConnected = 0, |
| 122 | BleSystemDisconnected = 1, | 121 | BleSystemDisconnected = 1, |
| 123 | BleSystemUartRx = 8, | 122 | BleSystemUartRx = 8, |
| 124 | BleSystemMidiRx = 10, | 123 | BleSystemMidiRx = 10, |
| 125 | }; | 124 | }; |
| 126 | 125 | ||
| 127 | // The SDEP.md file says 2MHz but the web page and the sample driver | 126 | // The SDEP.md file says 2MHz but the web page and the sample driver |
| 128 | // both use 4MHz | 127 | // both use 4MHz |
| 129 | #define SpiBusSpeed 4000000 | 128 | #define SpiBusSpeed 4000000 |
| 130 | 129 | ||
| 131 | #define SdepTimeout 150 /* milliseconds */ | 130 | #define SdepTimeout 150 /* milliseconds */ |
| 132 | #define SdepShortTimeout 10 /* milliseconds */ | 131 | #define SdepShortTimeout 10 /* milliseconds */ |
| 133 | #define SdepBackOff 25 /* microseconds */ | 132 | #define SdepBackOff 25 /* microseconds */ |
| 134 | #define BatteryUpdateInterval 10000 /* milliseconds */ | 133 | #define BatteryUpdateInterval 10000 /* milliseconds */ |
| 135 | 134 | ||
| 136 | static bool at_command(const char *cmd, char *resp, uint16_t resplen, | 135 | static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout = SdepTimeout); |
| 137 | bool verbose, uint16_t timeout = SdepTimeout); | 136 | static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose = false); |
| 138 | static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, | ||
| 139 | bool verbose = false); | ||
| 140 | 137 | ||
| 141 | struct SPI_Settings { | 138 | struct SPI_Settings { |
| 142 | uint8_t spcr, spsr; | 139 | uint8_t spcr, spsr; |
| 143 | }; | 140 | }; |
| 144 | 141 | ||
| 145 | static struct SPI_Settings spi; | 142 | static struct SPI_Settings spi; |
| 146 | 143 | ||
| 147 | // Initialize 4Mhz MSBFIRST MODE0 | 144 | // Initialize 4Mhz MSBFIRST MODE0 |
| 148 | void SPI_init(struct SPI_Settings *spi) { | 145 | void SPI_init(struct SPI_Settings *spi) { |
| 149 | spi->spcr = _BV(SPE) | _BV(MSTR); | 146 | spi->spcr = _BV(SPE) | _BV(MSTR); |
| 150 | spi->spsr = _BV(SPI2X); | 147 | spi->spsr = _BV(SPI2X); |
| 151 | 148 | ||
| 152 | static_assert(SpiBusSpeed == F_CPU / 2, "hard coded at 4Mhz"); | 149 | static_assert(SpiBusSpeed == F_CPU / 2, "hard coded at 4Mhz"); |
| 153 | 150 | ||
| 154 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { | 151 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { |
| 155 | // Ensure that SS is OUTPUT High | 152 | // Ensure that SS is OUTPUT High |
| 156 | digitalWrite(B0, PinLevelHigh); | 153 | digitalWrite(B0, PinLevelHigh); |
| 157 | pinMode(B0, PinDirectionOutput); | 154 | pinMode(B0, PinDirectionOutput); |
| 158 | 155 | ||
| 159 | SPCR |= _BV(MSTR); | 156 | SPCR |= _BV(MSTR); |
| 160 | SPCR |= _BV(SPE); | 157 | SPCR |= _BV(SPE); |
| 161 | pinMode(B1 /* SCK */, PinDirectionOutput); | 158 | pinMode(B1 /* SCK */, PinDirectionOutput); |
| 162 | pinMode(B2 /* MOSI */, PinDirectionOutput); | 159 | pinMode(B2 /* MOSI */, PinDirectionOutput); |
| 163 | } | 160 | } |
| 164 | } | 161 | } |
| 165 | 162 | ||
| 166 | static inline void SPI_begin(struct SPI_Settings*spi) { | 163 | static inline void SPI_begin(struct SPI_Settings *spi) { |
| 167 | SPCR = spi->spcr; | 164 | SPCR = spi->spcr; |
| 168 | SPSR = spi->spsr; | 165 | SPSR = spi->spsr; |
| 169 | } | 166 | } |
| 170 | 167 | ||
| 171 | static inline uint8_t SPI_TransferByte(uint8_t data) { | 168 | static inline uint8_t SPI_TransferByte(uint8_t data) { |
| 172 | SPDR = data; | 169 | SPDR = data; |
| 173 | asm volatile("nop"); | 170 | asm volatile("nop"); |
| 174 | while (!(SPSR & _BV(SPIF))) { | 171 | while (!(SPSR & _BV(SPIF))) { |
| 175 | ; // wait | 172 | ; // wait |
| 176 | } | 173 | } |
| 177 | return SPDR; | 174 | return SPDR; |
| 178 | } | 175 | } |
| 179 | 176 | ||
| 180 | static inline void spi_send_bytes(const uint8_t *buf, uint8_t len) { | 177 | static inline void spi_send_bytes(const uint8_t *buf, uint8_t len) { |
| 181 | if (len == 0) return; | 178 | if (len == 0) return; |
| 182 | const uint8_t *end = buf + len; | 179 | const uint8_t *end = buf + len; |
| 183 | while (buf < end) { | 180 | while (buf < end) { |
| 184 | SPDR = *buf; | 181 | SPDR = *buf; |
| 185 | while (!(SPSR & _BV(SPIF))) { | 182 | while (!(SPSR & _BV(SPIF))) { |
| 186 | ; // wait | 183 | ; // wait |
| 184 | } | ||
| 185 | ++buf; | ||
| 187 | } | 186 | } |
| 188 | ++buf; | ||
| 189 | } | ||
| 190 | } | 187 | } |
| 191 | 188 | ||
| 192 | static inline uint16_t spi_read_byte(void) { | 189 | static inline uint16_t spi_read_byte(void) { return SPI_TransferByte(0x00 /* dummy */); } |
| 193 | return SPI_TransferByte(0x00 /* dummy */); | ||
| 194 | } | ||
| 195 | 190 | ||
| 196 | static inline void spi_recv_bytes(uint8_t *buf, uint8_t len) { | 191 | static inline void spi_recv_bytes(uint8_t *buf, uint8_t len) { |
| 197 | const uint8_t *end = buf + len; | 192 | const uint8_t *end = buf + len; |
| 198 | if (len == 0) return; | 193 | if (len == 0) return; |
| 199 | while (buf < end) { | 194 | while (buf < end) { |
| 200 | SPDR = 0; // write a dummy to initiate read | 195 | SPDR = 0; // write a dummy to initiate read |
| 201 | while (!(SPSR & _BV(SPIF))) { | 196 | while (!(SPSR & _BV(SPIF))) { |
| 202 | ; // wait | 197 | ; // wait |
| 198 | } | ||
| 199 | *buf = SPDR; | ||
| 200 | ++buf; | ||
| 203 | } | 201 | } |
| 204 | *buf = SPDR; | ||
| 205 | ++buf; | ||
| 206 | } | ||
| 207 | } | 202 | } |
| 208 | 203 | ||
| 209 | #if 0 | 204 | #if 0 |
| @@ -223,600 +218,572 @@ static void dump_pkt(const struct sdep_msg *msg) { | |||
| 223 | 218 | ||
| 224 | // Send a single SDEP packet | 219 | // Send a single SDEP packet |
| 225 | static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) { | 220 | static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) { |
| 226 | SPI_begin(&spi); | 221 | SPI_begin(&spi); |
| 222 | |||
| 223 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | ||
| 224 | uint16_t timerStart = timer_read(); | ||
| 225 | bool success = false; | ||
| 226 | bool ready = false; | ||
| 227 | |||
| 228 | do { | ||
| 229 | ready = SPI_TransferByte(msg->type) != SdepSlaveNotReady; | ||
| 230 | if (ready) { | ||
| 231 | break; | ||
| 232 | } | ||
| 227 | 233 | ||
| 228 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | 234 | // Release it and let it initialize |
| 229 | uint16_t timerStart = timer_read(); | 235 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); |
| 230 | bool success = false; | 236 | _delay_us(SdepBackOff); |
| 231 | bool ready = false; | 237 | digitalWrite(AdafruitBleCSPin, PinLevelLow); |
| 238 | } while (timer_elapsed(timerStart) < timeout); | ||
| 232 | 239 | ||
| 233 | do { | ||
| 234 | ready = SPI_TransferByte(msg->type) != SdepSlaveNotReady; | ||
| 235 | if (ready) { | 240 | if (ready) { |
| 236 | break; | 241 | // Slave is ready; send the rest of the packet |
| 242 | spi_send_bytes(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload)) + msg->len); | ||
| 243 | success = true; | ||
| 237 | } | 244 | } |
| 238 | 245 | ||
| 239 | // Release it and let it initialize | ||
| 240 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | 246 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); |
| 241 | _delay_us(SdepBackOff); | ||
| 242 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | ||
| 243 | } while (timer_elapsed(timerStart) < timeout); | ||
| 244 | |||
| 245 | if (ready) { | ||
| 246 | // Slave is ready; send the rest of the packet | ||
| 247 | spi_send_bytes(&msg->cmd_low, | ||
| 248 | sizeof(*msg) - (1 + sizeof(msg->payload)) + msg->len); | ||
| 249 | success = true; | ||
| 250 | } | ||
| 251 | 247 | ||
| 252 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | 248 | return success; |
| 253 | |||
| 254 | return success; | ||
| 255 | } | 249 | } |
| 256 | 250 | ||
| 257 | static inline void sdep_build_pkt(struct sdep_msg *msg, uint16_t command, | 251 | static inline void sdep_build_pkt(struct sdep_msg *msg, uint16_t command, const uint8_t *payload, uint8_t len, bool moredata) { |
| 258 | const uint8_t *payload, uint8_t len, | 252 | msg->type = SdepCommand; |
| 259 | bool moredata) { | 253 | msg->cmd_low = command & 0xff; |
| 260 | msg->type = SdepCommand; | 254 | msg->cmd_high = command >> 8; |
| 261 | msg->cmd_low = command & 0xff; | 255 | msg->len = len; |
| 262 | msg->cmd_high = command >> 8; | 256 | msg->more = (moredata && len == SdepMaxPayload) ? 1 : 0; |
| 263 | msg->len = len; | ||
| 264 | msg->more = (moredata && len == SdepMaxPayload) ? 1 : 0; | ||
| 265 | 257 | ||
| 266 | static_assert(sizeof(*msg) == 20, "msg is correctly packed"); | 258 | static_assert(sizeof(*msg) == 20, "msg is correctly packed"); |
| 267 | 259 | ||
| 268 | memcpy(msg->payload, payload, len); | 260 | memcpy(msg->payload, payload, len); |
| 269 | } | 261 | } |
| 270 | 262 | ||
| 271 | // Read a single SDEP packet | 263 | // Read a single SDEP packet |
| 272 | static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) { | 264 | static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) { |
| 273 | bool success = false; | 265 | bool success = false; |
| 274 | uint16_t timerStart = timer_read(); | 266 | uint16_t timerStart = timer_read(); |
| 275 | bool ready = false; | 267 | bool ready = false; |
| 268 | |||
| 269 | do { | ||
| 270 | ready = digitalRead(AdafruitBleIRQPin); | ||
| 271 | if (ready) { | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | _delay_us(1); | ||
| 275 | } while (timer_elapsed(timerStart) < timeout); | ||
| 276 | 276 | ||
| 277 | do { | ||
| 278 | ready = digitalRead(AdafruitBleIRQPin); | ||
| 279 | if (ready) { | 277 | if (ready) { |
| 280 | break; | 278 | SPI_begin(&spi); |
| 281 | } | ||
| 282 | _delay_us(1); | ||
| 283 | } while (timer_elapsed(timerStart) < timeout); | ||
| 284 | 279 | ||
| 285 | if (ready) { | 280 | digitalWrite(AdafruitBleCSPin, PinLevelLow); |
| 286 | SPI_begin(&spi); | ||
| 287 | 281 | ||
| 288 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | 282 | do { |
| 283 | // Read the command type, waiting for the data to be ready | ||
| 284 | msg->type = spi_read_byte(); | ||
| 285 | if (msg->type == SdepSlaveNotReady || msg->type == SdepSlaveOverflow) { | ||
| 286 | // Release it and let it initialize | ||
| 287 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | ||
| 288 | _delay_us(SdepBackOff); | ||
| 289 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | ||
| 290 | continue; | ||
| 291 | } | ||
| 292 | |||
| 293 | // Read the rest of the header | ||
| 294 | spi_recv_bytes(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload))); | ||
| 295 | |||
| 296 | // and get the payload if there is any | ||
| 297 | if (msg->len <= SdepMaxPayload) { | ||
| 298 | spi_recv_bytes(msg->payload, msg->len); | ||
| 299 | } | ||
| 300 | success = true; | ||
| 301 | break; | ||
| 302 | } while (timer_elapsed(timerStart) < timeout); | ||
| 289 | 303 | ||
| 290 | do { | ||
| 291 | // Read the command type, waiting for the data to be ready | ||
| 292 | msg->type = spi_read_byte(); | ||
| 293 | if (msg->type == SdepSlaveNotReady || msg->type == SdepSlaveOverflow) { | ||
| 294 | // Release it and let it initialize | ||
| 295 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | 304 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); |
| 296 | _delay_us(SdepBackOff); | 305 | } |
| 297 | digitalWrite(AdafruitBleCSPin, PinLevelLow); | 306 | return success; |
| 298 | continue; | ||
| 299 | } | ||
| 300 | |||
| 301 | // Read the rest of the header | ||
| 302 | spi_recv_bytes(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload))); | ||
| 303 | |||
| 304 | // and get the payload if there is any | ||
| 305 | if (msg->len <= SdepMaxPayload) { | ||
| 306 | spi_recv_bytes(msg->payload, msg->len); | ||
| 307 | } | ||
| 308 | success = true; | ||
| 309 | break; | ||
| 310 | } while (timer_elapsed(timerStart) < timeout); | ||
| 311 | |||
| 312 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | ||
| 313 | } | ||
| 314 | return success; | ||
| 315 | } | 307 | } |
| 316 | 308 | ||
| 317 | static void resp_buf_read_one(bool greedy) { | 309 | static void resp_buf_read_one(bool greedy) { |
| 318 | uint16_t last_send; | 310 | uint16_t last_send; |
| 319 | if (!resp_buf.peek(last_send)) { | 311 | if (!resp_buf.peek(last_send)) { |
| 320 | return; | 312 | return; |
| 321 | } | 313 | } |
| 322 | 314 | ||
| 323 | if (digitalRead(AdafruitBleIRQPin)) { | 315 | if (digitalRead(AdafruitBleIRQPin)) { |
| 324 | struct sdep_msg msg; | 316 | struct sdep_msg msg; |
| 325 | 317 | ||
| 326 | again: | 318 | again: |
| 327 | if (sdep_recv_pkt(&msg, SdepTimeout)) { | 319 | if (sdep_recv_pkt(&msg, SdepTimeout)) { |
| 328 | if (!msg.more) { | 320 | if (!msg.more) { |
| 329 | // We got it; consume this entry | 321 | // We got it; consume this entry |
| 330 | resp_buf.get(last_send); | 322 | resp_buf.get(last_send); |
| 331 | dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); | 323 | dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); |
| 332 | } | 324 | } |
| 333 | 325 | ||
| 334 | if (greedy && resp_buf.peek(last_send) && digitalRead(AdafruitBleIRQPin)) { | 326 | if (greedy && resp_buf.peek(last_send) && digitalRead(AdafruitBleIRQPin)) { |
| 335 | goto again; | 327 | goto again; |
| 336 | } | 328 | } |
| 337 | } | 329 | } |
| 338 | 330 | ||
| 339 | } else if (timer_elapsed(last_send) > SdepTimeout * 2) { | 331 | } else if (timer_elapsed(last_send) > SdepTimeout * 2) { |
| 340 | dprintf("waiting_for_result: timeout, resp_buf size %d\n", | 332 | dprintf("waiting_for_result: timeout, resp_buf size %d\n", (int)resp_buf.size()); |
| 341 | (int)resp_buf.size()); | ||
| 342 | 333 | ||
| 343 | // Timed out: consume this entry | 334 | // Timed out: consume this entry |
| 344 | resp_buf.get(last_send); | 335 | resp_buf.get(last_send); |
| 345 | } | 336 | } |
| 346 | } | 337 | } |
| 347 | 338 | ||
| 348 | static void send_buf_send_one(uint16_t timeout = SdepTimeout) { | 339 | static void send_buf_send_one(uint16_t timeout = SdepTimeout) { |
| 349 | struct queue_item item; | 340 | struct queue_item item; |
| 350 | 341 | ||
| 351 | // Don't send anything more until we get an ACK | 342 | // Don't send anything more until we get an ACK |
| 352 | if (!resp_buf.empty()) { | 343 | if (!resp_buf.empty()) { |
| 353 | return; | 344 | return; |
| 354 | } | 345 | } |
| 355 | 346 | ||
| 356 | if (!send_buf.peek(item)) { | 347 | if (!send_buf.peek(item)) { |
| 357 | return; | 348 | return; |
| 358 | } | 349 | } |
| 359 | if (process_queue_item(&item, timeout)) { | 350 | if (process_queue_item(&item, timeout)) { |
| 360 | // commit that peek | 351 | // commit that peek |
| 361 | send_buf.get(item); | 352 | send_buf.get(item); |
| 362 | dprintf("send_buf_send_one: have %d remaining\n", (int)send_buf.size()); | 353 | dprintf("send_buf_send_one: have %d remaining\n", (int)send_buf.size()); |
| 363 | } else { | 354 | } else { |
| 364 | dprint("failed to send, will retry\n"); | 355 | dprint("failed to send, will retry\n"); |
| 365 | _delay_ms(SdepTimeout); | 356 | _delay_ms(SdepTimeout); |
| 366 | resp_buf_read_one(true); | 357 | resp_buf_read_one(true); |
| 367 | } | 358 | } |
| 368 | } | 359 | } |
| 369 | 360 | ||
| 370 | static void resp_buf_wait(const char *cmd) { | 361 | static void resp_buf_wait(const char *cmd) { |
| 371 | bool didPrint = false; | 362 | bool didPrint = false; |
| 372 | while (!resp_buf.empty()) { | 363 | while (!resp_buf.empty()) { |
| 373 | if (!didPrint) { | 364 | if (!didPrint) { |
| 374 | dprintf("wait on buf for %s\n", cmd); | 365 | dprintf("wait on buf for %s\n", cmd); |
| 375 | didPrint = true; | 366 | didPrint = true; |
| 367 | } | ||
| 368 | resp_buf_read_one(true); | ||
| 376 | } | 369 | } |
| 377 | resp_buf_read_one(true); | ||
| 378 | } | ||
| 379 | } | 370 | } |
| 380 | 371 | ||
| 381 | static bool ble_init(void) { | 372 | static bool ble_init(void) { |
| 382 | state.initialized = false; | 373 | state.initialized = false; |
| 383 | state.configured = false; | 374 | state.configured = false; |
| 384 | state.is_connected = false; | 375 | state.is_connected = false; |
| 385 | 376 | ||
| 386 | pinMode(AdafruitBleIRQPin, PinDirectionInput); | 377 | pinMode(AdafruitBleIRQPin, PinDirectionInput); |
| 387 | pinMode(AdafruitBleCSPin, PinDirectionOutput); | 378 | pinMode(AdafruitBleCSPin, PinDirectionOutput); |
| 388 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); | 379 | digitalWrite(AdafruitBleCSPin, PinLevelHigh); |
| 389 | 380 | ||
| 390 | SPI_init(&spi); | 381 | SPI_init(&spi); |
| 391 | 382 | ||
| 392 | // Perform a hardware reset | 383 | // Perform a hardware reset |
| 393 | pinMode(AdafruitBleResetPin, PinDirectionOutput); | 384 | pinMode(AdafruitBleResetPin, PinDirectionOutput); |
| 394 | digitalWrite(AdafruitBleResetPin, PinLevelHigh); | 385 | digitalWrite(AdafruitBleResetPin, PinLevelHigh); |
| 395 | digitalWrite(AdafruitBleResetPin, PinLevelLow); | 386 | digitalWrite(AdafruitBleResetPin, PinLevelLow); |
| 396 | _delay_ms(10); | 387 | _delay_ms(10); |
| 397 | digitalWrite(AdafruitBleResetPin, PinLevelHigh); | 388 | digitalWrite(AdafruitBleResetPin, PinLevelHigh); |
| 398 | 389 | ||
| 399 | _delay_ms(1000); // Give it a second to initialize | 390 | _delay_ms(1000); // Give it a second to initialize |
| 400 | 391 | ||
| 401 | state.initialized = true; | 392 | state.initialized = true; |
| 402 | return state.initialized; | 393 | return state.initialized; |
| 403 | } | 394 | } |
| 404 | 395 | ||
| 405 | static inline uint8_t min(uint8_t a, uint8_t b) { | 396 | static inline uint8_t min(uint8_t a, uint8_t b) { return a < b ? a : b; } |
| 406 | return a < b ? a : b; | ||
| 407 | } | ||
| 408 | 397 | ||
| 409 | static bool read_response(char *resp, uint16_t resplen, bool verbose) { | 398 | static bool read_response(char *resp, uint16_t resplen, bool verbose) { |
| 410 | char *dest = resp; | 399 | char *dest = resp; |
| 411 | char *end = dest + resplen; | 400 | char *end = dest + resplen; |
| 412 | 401 | ||
| 413 | while (true) { | 402 | while (true) { |
| 414 | struct sdep_msg msg; | 403 | struct sdep_msg msg; |
| 415 | 404 | ||
| 416 | if (!sdep_recv_pkt(&msg, 2 * SdepTimeout)) { | 405 | if (!sdep_recv_pkt(&msg, 2 * SdepTimeout)) { |
| 417 | dprint("sdep_recv_pkt failed\n"); | 406 | dprint("sdep_recv_pkt failed\n"); |
| 418 | return false; | 407 | return false; |
| 408 | } | ||
| 409 | |||
| 410 | if (msg.type != SdepResponse) { | ||
| 411 | *resp = 0; | ||
| 412 | return false; | ||
| 413 | } | ||
| 414 | |||
| 415 | uint8_t len = min(msg.len, end - dest); | ||
| 416 | if (len > 0) { | ||
| 417 | memcpy(dest, msg.payload, len); | ||
| 418 | dest += len; | ||
| 419 | } | ||
| 420 | |||
| 421 | if (!msg.more) { | ||
| 422 | // No more data is expected! | ||
| 423 | break; | ||
| 424 | } | ||
| 419 | } | 425 | } |
| 420 | 426 | ||
| 421 | if (msg.type != SdepResponse) { | 427 | // Ensure the response is NUL terminated |
| 422 | *resp = 0; | 428 | *dest = 0; |
| 423 | return false; | ||
| 424 | } | ||
| 425 | 429 | ||
| 426 | uint8_t len = min(msg.len, end - dest); | 430 | // "Parse" the result text; we want to snip off the trailing OK or ERROR line |
| 427 | if (len > 0) { | 431 | // Rewind past the possible trailing CRLF so that we can strip it |
| 428 | memcpy(dest, msg.payload, len); | 432 | --dest; |
| 429 | dest += len; | 433 | while (dest > resp && (dest[0] == '\n' || dest[0] == '\r')) { |
| 434 | *dest = 0; | ||
| 435 | --dest; | ||
| 430 | } | 436 | } |
| 431 | 437 | ||
| 432 | if (!msg.more) { | 438 | // Look back for start of preceeding line |
| 433 | // No more data is expected! | 439 | char *last_line = strrchr(resp, '\n'); |
| 434 | break; | 440 | if (last_line) { |
| 441 | ++last_line; | ||
| 442 | } else { | ||
| 443 | last_line = resp; | ||
| 435 | } | 444 | } |
| 436 | } | ||
| 437 | |||
| 438 | // Ensure the response is NUL terminated | ||
| 439 | *dest = 0; | ||
| 440 | 445 | ||
| 441 | // "Parse" the result text; we want to snip off the trailing OK or ERROR line | 446 | bool success = false; |
| 442 | // Rewind past the possible trailing CRLF so that we can strip it | 447 | static const char kOK[] PROGMEM = "OK"; |
| 443 | --dest; | ||
| 444 | while (dest > resp && (dest[0] == '\n' || dest[0] == '\r')) { | ||
| 445 | *dest = 0; | ||
| 446 | --dest; | ||
| 447 | } | ||
| 448 | 448 | ||
| 449 | // Look back for start of preceeding line | 449 | success = !strcmp_P(last_line, kOK); |
| 450 | char *last_line = strrchr(resp, '\n'); | ||
| 451 | if (last_line) { | ||
| 452 | ++last_line; | ||
| 453 | } else { | ||
| 454 | last_line = resp; | ||
| 455 | } | ||
| 456 | 450 | ||
| 457 | bool success = false; | 451 | if (verbose || !success) { |
| 458 | static const char kOK[] PROGMEM = "OK"; | 452 | dprintf("result: %s\n", resp); |
| 453 | } | ||
| 454 | return success; | ||
| 455 | } | ||
| 459 | 456 | ||
| 460 | success = !strcmp_P(last_line, kOK ); | 457 | static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout) { |
| 458 | const char * end = cmd + strlen(cmd); | ||
| 459 | struct sdep_msg msg; | ||
| 461 | 460 | ||
| 462 | if (verbose || !success) { | 461 | if (verbose) { |
| 463 | dprintf("result: %s\n", resp); | 462 | dprintf("ble send: %s\n", cmd); |
| 464 | } | 463 | } |
| 465 | return success; | ||
| 466 | } | ||
| 467 | 464 | ||
| 468 | static bool at_command(const char *cmd, char *resp, uint16_t resplen, | 465 | if (resp) { |
| 469 | bool verbose, uint16_t timeout) { | 466 | // They want to decode the response, so we need to flush and wait |
| 470 | const char *end = cmd + strlen(cmd); | 467 | // for all pending I/O to finish before we start this one, so |
| 471 | struct sdep_msg msg; | 468 | // that we don't confuse the results |
| 472 | 469 | resp_buf_wait(cmd); | |
| 473 | if (verbose) { | 470 | *resp = 0; |
| 474 | dprintf("ble send: %s\n", cmd); | ||
| 475 | } | ||
| 476 | |||
| 477 | if (resp) { | ||
| 478 | // They want to decode the response, so we need to flush and wait | ||
| 479 | // for all pending I/O to finish before we start this one, so | ||
| 480 | // that we don't confuse the results | ||
| 481 | resp_buf_wait(cmd); | ||
| 482 | *resp = 0; | ||
| 483 | } | ||
| 484 | |||
| 485 | // Fragment the command into a series of SDEP packets | ||
| 486 | while (end - cmd > SdepMaxPayload) { | ||
| 487 | sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, SdepMaxPayload, true); | ||
| 488 | if (!sdep_send_pkt(&msg, timeout)) { | ||
| 489 | return false; | ||
| 490 | } | 471 | } |
| 491 | cmd += SdepMaxPayload; | ||
| 492 | } | ||
| 493 | 472 | ||
| 494 | sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, end - cmd, false); | 473 | // Fragment the command into a series of SDEP packets |
| 495 | if (!sdep_send_pkt(&msg, timeout)) { | 474 | while (end - cmd > SdepMaxPayload) { |
| 496 | return false; | 475 | sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, SdepMaxPayload, true); |
| 497 | } | 476 | if (!sdep_send_pkt(&msg, timeout)) { |
| 477 | return false; | ||
| 478 | } | ||
| 479 | cmd += SdepMaxPayload; | ||
| 480 | } | ||
| 498 | 481 | ||
| 499 | if (resp == NULL) { | 482 | sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, end - cmd, false); |
| 500 | auto now = timer_read(); | 483 | if (!sdep_send_pkt(&msg, timeout)) { |
| 501 | while (!resp_buf.enqueue(now)) { | 484 | return false; |
| 502 | resp_buf_read_one(false); | ||
| 503 | } | 485 | } |
| 504 | auto later = timer_read(); | 486 | |
| 505 | if (TIMER_DIFF_16(later, now) > 0) { | 487 | if (resp == NULL) { |
| 506 | dprintf("waited %dms for resp_buf\n", TIMER_DIFF_16(later, now)); | 488 | auto now = timer_read(); |
| 489 | while (!resp_buf.enqueue(now)) { | ||
| 490 | resp_buf_read_one(false); | ||
| 491 | } | ||
| 492 | auto later = timer_read(); | ||
| 493 | if (TIMER_DIFF_16(later, now) > 0) { | ||
| 494 | dprintf("waited %dms for resp_buf\n", TIMER_DIFF_16(later, now)); | ||
| 495 | } | ||
| 496 | return true; | ||
| 507 | } | 497 | } |
| 508 | return true; | ||
| 509 | } | ||
| 510 | 498 | ||
| 511 | return read_response(resp, resplen, verbose); | 499 | return read_response(resp, resplen, verbose); |
| 512 | } | 500 | } |
| 513 | 501 | ||
| 514 | bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) { | 502 | bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) { |
| 515 | auto cmdbuf = (char *)alloca(strlen_P(cmd) + 1); | 503 | auto cmdbuf = (char *)alloca(strlen_P(cmd) + 1); |
| 516 | strcpy_P(cmdbuf, cmd); | 504 | strcpy_P(cmdbuf, cmd); |
| 517 | return at_command(cmdbuf, resp, resplen, verbose); | 505 | return at_command(cmdbuf, resp, resplen, verbose); |
| 518 | } | 506 | } |
| 519 | 507 | ||
| 520 | bool adafruit_ble_is_connected(void) { | 508 | bool adafruit_ble_is_connected(void) { return state.is_connected; } |
| 521 | return state.is_connected; | ||
| 522 | } | ||
| 523 | 509 | ||
| 524 | bool adafruit_ble_enable_keyboard(void) { | 510 | bool adafruit_ble_enable_keyboard(void) { |
| 525 | char resbuf[128]; | 511 | char resbuf[128]; |
| 526 | 512 | ||
| 527 | if (!state.initialized && !ble_init()) { | 513 | if (!state.initialized && !ble_init()) { |
| 528 | return false; | 514 | return false; |
| 529 | } | 515 | } |
| 530 | 516 | ||
| 531 | state.configured = false; | 517 | state.configured = false; |
| 532 | 518 | ||
| 533 | // Disable command echo | 519 | // Disable command echo |
| 534 | static const char kEcho[] PROGMEM = "ATE=0"; | 520 | static const char kEcho[] PROGMEM = "ATE=0"; |
| 535 | // Make the advertised name match the keyboard | 521 | // Make the advertised name match the keyboard |
| 536 | static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT); | 522 | static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT); |
| 537 | // Turn on keyboard support | 523 | // Turn on keyboard support |
| 538 | static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1"; | 524 | static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1"; |
| 539 | 525 | ||
| 540 | // Adjust intervals to improve latency. This causes the "central" | 526 | // Adjust intervals to improve latency. This causes the "central" |
| 541 | // system (computer/tablet) to poll us every 10-30 ms. We can't | 527 | // system (computer/tablet) to poll us every 10-30 ms. We can't |
| 542 | // set a smaller value than 10ms, and 30ms seems to be the natural | 528 | // set a smaller value than 10ms, and 30ms seems to be the natural |
| 543 | // processing time on my macbook. Keeping it constrained to that | 529 | // processing time on my macbook. Keeping it constrained to that |
| 544 | // feels reasonable to type to. | 530 | // feels reasonable to type to. |
| 545 | static const char kGapIntervals[] PROGMEM = "AT+GAPINTERVALS=10,30,,"; | 531 | static const char kGapIntervals[] PROGMEM = "AT+GAPINTERVALS=10,30,,"; |
| 546 | 532 | ||
| 547 | // Reset the device so that it picks up the above changes | 533 | // Reset the device so that it picks up the above changes |
| 548 | static const char kATZ[] PROGMEM = "ATZ"; | 534 | static const char kATZ[] PROGMEM = "ATZ"; |
| 549 | 535 | ||
| 550 | // Turn down the power level a bit | 536 | // Turn down the power level a bit |
| 551 | static const char kPower[] PROGMEM = "AT+BLEPOWERLEVEL=-12"; | 537 | static const char kPower[] PROGMEM = "AT+BLEPOWERLEVEL=-12"; |
| 552 | static PGM_P const configure_commands[] PROGMEM = { | 538 | static PGM_P const configure_commands[] PROGMEM = { |
| 553 | kEcho, | 539 | kEcho, kGapIntervals, kGapDevName, kHidEnOn, kPower, kATZ, |
| 554 | kGapIntervals, | 540 | }; |
| 555 | kGapDevName, | 541 | |
| 556 | kHidEnOn, | 542 | uint8_t i; |
| 557 | kPower, | 543 | for (i = 0; i < sizeof(configure_commands) / sizeof(configure_commands[0]); ++i) { |
| 558 | kATZ, | 544 | PGM_P cmd; |
| 559 | }; | 545 | memcpy_P(&cmd, configure_commands + i, sizeof(cmd)); |
| 560 | 546 | ||
| 561 | uint8_t i; | 547 | if (!at_command_P(cmd, resbuf, sizeof(resbuf))) { |
| 562 | for (i = 0; i < sizeof(configure_commands) / sizeof(configure_commands[0]); | 548 | dprintf("failed BLE command: %S: %s\n", cmd, resbuf); |
| 563 | ++i) { | 549 | goto fail; |
| 564 | PGM_P cmd; | 550 | } |
| 565 | memcpy_P(&cmd, configure_commands + i, sizeof(cmd)); | 551 | } |
| 566 | 552 | ||
| 567 | if (!at_command_P(cmd, resbuf, sizeof(resbuf))) { | 553 | state.configured = true; |
| 568 | dprintf("failed BLE command: %S: %s\n", cmd, resbuf); | 554 | |
| 569 | goto fail; | 555 | // Check connection status in a little while; allow the ATZ time |
| 570 | } | 556 | // to kick in. |
| 571 | } | 557 | state.last_connection_update = timer_read(); |
| 572 | |||
| 573 | state.configured = true; | ||
| 574 | |||
| 575 | // Check connection status in a little while; allow the ATZ time | ||
| 576 | // to kick in. | ||
| 577 | state.last_connection_update = timer_read(); | ||
| 578 | fail: | 558 | fail: |
| 579 | return state.configured; | 559 | return state.configured; |
| 580 | } | 560 | } |
| 581 | 561 | ||
| 582 | static void set_connected(bool connected) { | 562 | static void set_connected(bool connected) { |
| 583 | if (connected != state.is_connected) { | 563 | if (connected != state.is_connected) { |
| 584 | if (connected) { | 564 | if (connected) { |
| 585 | print("****** BLE CONNECT!!!!\n"); | 565 | print("****** BLE CONNECT!!!!\n"); |
| 586 | } else { | 566 | } else { |
| 587 | print("****** BLE DISCONNECT!!!!\n"); | 567 | print("****** BLE DISCONNECT!!!!\n"); |
| 588 | } | 568 | } |
| 589 | state.is_connected = connected; | 569 | state.is_connected = connected; |
| 590 | 570 | ||
| 591 | // TODO: if modifiers are down on the USB interface and | 571 | // TODO: if modifiers are down on the USB interface and |
| 592 | // we cut over to BLE or vice versa, they will remain stuck. | 572 | // we cut over to BLE or vice versa, they will remain stuck. |
| 593 | // This feels like a good point to do something like clearing | 573 | // This feels like a good point to do something like clearing |
| 594 | // the keyboard and/or generating a fake all keys up message. | 574 | // the keyboard and/or generating a fake all keys up message. |
| 595 | // However, I've noticed that it takes a couple of seconds | 575 | // However, I've noticed that it takes a couple of seconds |
| 596 | // for macOS to to start recognizing key presses after BLE | 576 | // for macOS to to start recognizing key presses after BLE |
| 597 | // is in the connected state, so I worry that doing that | 577 | // is in the connected state, so I worry that doing that |
| 598 | // here may not be good enough. | 578 | // here may not be good enough. |
| 599 | } | 579 | } |
| 600 | } | 580 | } |
| 601 | 581 | ||
| 602 | void adafruit_ble_task(void) { | 582 | void adafruit_ble_task(void) { |
| 603 | char resbuf[48]; | 583 | char resbuf[48]; |
| 604 | |||
| 605 | if (!state.configured && !adafruit_ble_enable_keyboard()) { | ||
| 606 | return; | ||
| 607 | } | ||
| 608 | resp_buf_read_one(true); | ||
| 609 | send_buf_send_one(SdepShortTimeout); | ||
| 610 | |||
| 611 | if (resp_buf.empty() && (state.event_flags & UsingEvents) && | ||
| 612 | digitalRead(AdafruitBleIRQPin)) { | ||
| 613 | // Must be an event update | ||
| 614 | if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { | ||
| 615 | uint32_t mask = strtoul(resbuf, NULL, 16); | ||
| 616 | |||
| 617 | if (mask & BleSystemConnected) { | ||
| 618 | set_connected(true); | ||
| 619 | } else if (mask & BleSystemDisconnected) { | ||
| 620 | set_connected(false); | ||
| 621 | } | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | if (timer_elapsed(state.last_connection_update) > ConnectionUpdateInterval) { | ||
| 626 | bool shouldPoll = true; | ||
| 627 | if (!(state.event_flags & ProbedEvents)) { | ||
| 628 | // Request notifications about connection status changes. | ||
| 629 | // This only works in SPIFRIEND firmware > 0.6.7, which is why | ||
| 630 | // we check for this conditionally here. | ||
| 631 | // Note that at the time of writing, HID reports only work correctly | ||
| 632 | // with Apple products on firmware version 0.6.7! | ||
| 633 | // https://forums.adafruit.com/viewtopic.php?f=8&t=104052 | ||
| 634 | if (at_command_P(PSTR("AT+EVENTENABLE=0x1"), resbuf, sizeof(resbuf))) { | ||
| 635 | at_command_P(PSTR("AT+EVENTENABLE=0x2"), resbuf, sizeof(resbuf)); | ||
| 636 | state.event_flags |= UsingEvents; | ||
| 637 | } | ||
| 638 | state.event_flags |= ProbedEvents; | ||
| 639 | |||
| 640 | // leave shouldPoll == true so that we check at least once | ||
| 641 | // before relying solely on events | ||
| 642 | } else { | ||
| 643 | shouldPoll = false; | ||
| 644 | } | ||
| 645 | 584 | ||
| 646 | static const char kGetConn[] PROGMEM = "AT+GAPGETCONN"; | 585 | if (!state.configured && !adafruit_ble_enable_keyboard()) { |
| 647 | state.last_connection_update = timer_read(); | 586 | return; |
| 587 | } | ||
| 588 | resp_buf_read_one(true); | ||
| 589 | send_buf_send_one(SdepShortTimeout); | ||
| 590 | |||
| 591 | if (resp_buf.empty() && (state.event_flags & UsingEvents) && digitalRead(AdafruitBleIRQPin)) { | ||
| 592 | // Must be an event update | ||
| 593 | if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { | ||
| 594 | uint32_t mask = strtoul(resbuf, NULL, 16); | ||
| 595 | |||
| 596 | if (mask & BleSystemConnected) { | ||
| 597 | set_connected(true); | ||
| 598 | } else if (mask & BleSystemDisconnected) { | ||
| 599 | set_connected(false); | ||
| 600 | } | ||
| 601 | } | ||
| 602 | } | ||
| 648 | 603 | ||
| 649 | if (at_command_P(kGetConn, resbuf, sizeof(resbuf))) { | 604 | if (timer_elapsed(state.last_connection_update) > ConnectionUpdateInterval) { |
| 650 | set_connected(atoi(resbuf)); | 605 | bool shouldPoll = true; |
| 606 | if (!(state.event_flags & ProbedEvents)) { | ||
| 607 | // Request notifications about connection status changes. | ||
| 608 | // This only works in SPIFRIEND firmware > 0.6.7, which is why | ||
| 609 | // we check for this conditionally here. | ||
| 610 | // Note that at the time of writing, HID reports only work correctly | ||
| 611 | // with Apple products on firmware version 0.6.7! | ||
| 612 | // https://forums.adafruit.com/viewtopic.php?f=8&t=104052 | ||
| 613 | if (at_command_P(PSTR("AT+EVENTENABLE=0x1"), resbuf, sizeof(resbuf))) { | ||
| 614 | at_command_P(PSTR("AT+EVENTENABLE=0x2"), resbuf, sizeof(resbuf)); | ||
| 615 | state.event_flags |= UsingEvents; | ||
| 616 | } | ||
| 617 | state.event_flags |= ProbedEvents; | ||
| 618 | |||
| 619 | // leave shouldPoll == true so that we check at least once | ||
| 620 | // before relying solely on events | ||
| 621 | } else { | ||
| 622 | shouldPoll = false; | ||
| 623 | } | ||
| 624 | |||
| 625 | static const char kGetConn[] PROGMEM = "AT+GAPGETCONN"; | ||
| 626 | state.last_connection_update = timer_read(); | ||
| 627 | |||
| 628 | if (at_command_P(kGetConn, resbuf, sizeof(resbuf))) { | ||
| 629 | set_connected(atoi(resbuf)); | ||
| 630 | } | ||
| 651 | } | 631 | } |
| 652 | } | ||
| 653 | 632 | ||
| 654 | #ifdef SAMPLE_BATTERY | 633 | #ifdef SAMPLE_BATTERY |
| 655 | // I don't know if this really does anything useful yet; the reported | 634 | // I don't know if this really does anything useful yet; the reported |
| 656 | // voltage level always seems to be around 3200mV. We may want to just rip | 635 | // voltage level always seems to be around 3200mV. We may want to just rip |
| 657 | // this code out. | 636 | // this code out. |
| 658 | if (timer_elapsed(state.last_battery_update) > BatteryUpdateInterval && | 637 | if (timer_elapsed(state.last_battery_update) > BatteryUpdateInterval && resp_buf.empty()) { |
| 659 | resp_buf.empty()) { | 638 | state.last_battery_update = timer_read(); |
| 660 | state.last_battery_update = timer_read(); | 639 | |
| 661 | 640 | if (at_command_P(PSTR("AT+HWVBAT"), resbuf, sizeof(resbuf))) { | |
| 662 | if (at_command_P(PSTR("AT+HWVBAT"), resbuf, sizeof(resbuf))) { | 641 | state.vbat = atoi(resbuf); |
| 663 | state.vbat = atoi(resbuf); | 642 | } |
| 664 | } | 643 | } |
| 665 | } | ||
| 666 | #endif | 644 | #endif |
| 667 | } | 645 | } |
| 668 | 646 | ||
| 669 | static bool process_queue_item(struct queue_item *item, uint16_t timeout) { | 647 | static bool process_queue_item(struct queue_item *item, uint16_t timeout) { |
| 670 | char cmdbuf[48]; | 648 | char cmdbuf[48]; |
| 671 | char fmtbuf[64]; | 649 | char fmtbuf[64]; |
| 672 | 650 | ||
| 673 | // Arrange to re-check connection after keys have settled | 651 | // Arrange to re-check connection after keys have settled |
| 674 | state.last_connection_update = timer_read(); | 652 | state.last_connection_update = timer_read(); |
| 675 | 653 | ||
| 676 | #if 1 | 654 | #if 1 |
| 677 | if (TIMER_DIFF_16(state.last_connection_update, item->added) > 0) { | 655 | if (TIMER_DIFF_16(state.last_connection_update, item->added) > 0) { |
| 678 | dprintf("send latency %dms\n", | 656 | dprintf("send latency %dms\n", TIMER_DIFF_16(state.last_connection_update, item->added)); |
| 679 | TIMER_DIFF_16(state.last_connection_update, item->added)); | 657 | } |
| 680 | } | ||
| 681 | #endif | 658 | #endif |
| 682 | 659 | ||
| 683 | switch (item->queue_type) { | 660 | switch (item->queue_type) { |
| 684 | case QTKeyReport: | 661 | case QTKeyReport: |
| 685 | strcpy_P(fmtbuf, | 662 | strcpy_P(fmtbuf, PSTR("AT+BLEKEYBOARDCODE=%02x-00-%02x-%02x-%02x-%02x-%02x-%02x")); |
| 686 | PSTR("AT+BLEKEYBOARDCODE=%02x-00-%02x-%02x-%02x-%02x-%02x-%02x")); | 663 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->key.modifier, item->key.keys[0], item->key.keys[1], item->key.keys[2], item->key.keys[3], item->key.keys[4], item->key.keys[5]); |
| 687 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->key.modifier, | 664 | return at_command(cmdbuf, NULL, 0, true, timeout); |
| 688 | item->key.keys[0], item->key.keys[1], item->key.keys[2], | ||
| 689 | item->key.keys[3], item->key.keys[4], item->key.keys[5]); | ||
| 690 | return at_command(cmdbuf, NULL, 0, true, timeout); | ||
| 691 | 665 | ||
| 692 | case QTConsumer: | 666 | case QTConsumer: |
| 693 | strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x")); | 667 | strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x")); |
| 694 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer); | 668 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer); |
| 695 | return at_command(cmdbuf, NULL, 0, true, timeout); | 669 | return at_command(cmdbuf, NULL, 0, true, timeout); |
| 696 | 670 | ||
| 697 | #ifdef MOUSE_ENABLE | 671 | #ifdef MOUSE_ENABLE |
| 698 | case QTMouseMove: | 672 | case QTMouseMove: |
| 699 | strcpy_P(fmtbuf, PSTR("AT+BLEHIDMOUSEMOVE=%d,%d,%d,%d")); | 673 | strcpy_P(fmtbuf, PSTR("AT+BLEHIDMOUSEMOVE=%d,%d,%d,%d")); |
| 700 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->mousemove.x, | 674 | snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->mousemove.x, item->mousemove.y, item->mousemove.scroll, item->mousemove.pan); |
| 701 | item->mousemove.y, item->mousemove.scroll, item->mousemove.pan); | 675 | if (!at_command(cmdbuf, NULL, 0, true, timeout)) { |
| 702 | if (!at_command(cmdbuf, NULL, 0, true, timeout)) { | 676 | return false; |
| 703 | return false; | 677 | } |
| 704 | } | 678 | strcpy_P(cmdbuf, PSTR("AT+BLEHIDMOUSEBUTTON=")); |
| 705 | strcpy_P(cmdbuf, PSTR("AT+BLEHIDMOUSEBUTTON=")); | 679 | if (item->mousemove.buttons & MOUSE_BTN1) { |
| 706 | if (item->mousemove.buttons & MOUSE_BTN1) { | 680 | strcat(cmdbuf, "L"); |
| 707 | strcat(cmdbuf, "L"); | 681 | } |
| 708 | } | 682 | if (item->mousemove.buttons & MOUSE_BTN2) { |
| 709 | if (item->mousemove.buttons & MOUSE_BTN2) { | 683 | strcat(cmdbuf, "R"); |
| 710 | strcat(cmdbuf, "R"); | 684 | } |
| 711 | } | 685 | if (item->mousemove.buttons & MOUSE_BTN3) { |
| 712 | if (item->mousemove.buttons & MOUSE_BTN3) { | 686 | strcat(cmdbuf, "M"); |
| 713 | strcat(cmdbuf, "M"); | 687 | } |
| 714 | } | 688 | if (item->mousemove.buttons == 0) { |
| 715 | if (item->mousemove.buttons == 0) { | 689 | strcat(cmdbuf, "0"); |
| 716 | strcat(cmdbuf, "0"); | 690 | } |
| 717 | } | 691 | return at_command(cmdbuf, NULL, 0, true, timeout); |
| 718 | return at_command(cmdbuf, NULL, 0, true, timeout); | ||
| 719 | #endif | 692 | #endif |
| 720 | default: | 693 | default: |
| 721 | return true; | 694 | return true; |
| 722 | } | ||
| 723 | } | ||
| 724 | |||
| 725 | bool adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, | ||
| 726 | uint8_t nkeys) { | ||
| 727 | struct queue_item item; | ||
| 728 | bool didWait = false; | ||
| 729 | |||
| 730 | item.queue_type = QTKeyReport; | ||
| 731 | item.key.modifier = hid_modifier_mask; | ||
| 732 | item.added = timer_read(); | ||
| 733 | |||
| 734 | while (nkeys >= 0) { | ||
| 735 | item.key.keys[0] = keys[0]; | ||
| 736 | item.key.keys[1] = nkeys >= 1 ? keys[1] : 0; | ||
| 737 | item.key.keys[2] = nkeys >= 2 ? keys[2] : 0; | ||
| 738 | item.key.keys[3] = nkeys >= 3 ? keys[3] : 0; | ||
| 739 | item.key.keys[4] = nkeys >= 4 ? keys[4] : 0; | ||
| 740 | item.key.keys[5] = nkeys >= 5 ? keys[5] : 0; | ||
| 741 | |||
| 742 | if (!send_buf.enqueue(item)) { | ||
| 743 | if (!didWait) { | ||
| 744 | dprint("wait for buf space\n"); | ||
| 745 | didWait = true; | ||
| 746 | } | ||
| 747 | send_buf_send_one(); | ||
| 748 | continue; | ||
| 749 | } | 695 | } |
| 696 | } | ||
| 750 | 697 | ||
| 751 | if (nkeys <= 6) { | 698 | bool adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) { |
| 752 | return true; | 699 | struct queue_item item; |
| 700 | bool didWait = false; | ||
| 701 | |||
| 702 | item.queue_type = QTKeyReport; | ||
| 703 | item.key.modifier = hid_modifier_mask; | ||
| 704 | item.added = timer_read(); | ||
| 705 | |||
| 706 | while (nkeys >= 0) { | ||
| 707 | item.key.keys[0] = keys[0]; | ||
| 708 | item.key.keys[1] = nkeys >= 1 ? keys[1] : 0; | ||
| 709 | item.key.keys[2] = nkeys >= 2 ? keys[2] : 0; | ||
| 710 | item.key.keys[3] = nkeys >= 3 ? keys[3] : 0; | ||
| 711 | item.key.keys[4] = nkeys >= 4 ? keys[4] : 0; | ||
| 712 | item.key.keys[5] = nkeys >= 5 ? keys[5] : 0; | ||
| 713 | |||
| 714 | if (!send_buf.enqueue(item)) { | ||
| 715 | if (!didWait) { | ||
| 716 | dprint("wait for buf space\n"); | ||
| 717 | didWait = true; | ||
| 718 | } | ||
| 719 | send_buf_send_one(); | ||
| 720 | continue; | ||
| 721 | } | ||
| 722 | |||
| 723 | if (nkeys <= 6) { | ||
| 724 | return true; | ||
| 725 | } | ||
| 726 | |||
| 727 | nkeys -= 6; | ||
| 728 | keys += 6; | ||
| 753 | } | 729 | } |
| 754 | 730 | ||
| 755 | nkeys -= 6; | 731 | return true; |
| 756 | keys += 6; | ||
| 757 | } | ||
| 758 | |||
| 759 | return true; | ||
| 760 | } | 732 | } |
| 761 | 733 | ||
| 762 | bool adafruit_ble_send_consumer_key(uint16_t keycode, int hold_duration) { | 734 | bool adafruit_ble_send_consumer_key(uint16_t keycode, int hold_duration) { |
| 763 | struct queue_item item; | 735 | struct queue_item item; |
| 764 | 736 | ||
| 765 | item.queue_type = QTConsumer; | 737 | item.queue_type = QTConsumer; |
| 766 | item.consumer = keycode; | 738 | item.consumer = keycode; |
| 767 | 739 | ||
| 768 | while (!send_buf.enqueue(item)) { | 740 | while (!send_buf.enqueue(item)) { |
| 769 | send_buf_send_one(); | 741 | send_buf_send_one(); |
| 770 | } | 742 | } |
| 771 | return true; | 743 | return true; |
| 772 | } | 744 | } |
| 773 | 745 | ||
| 774 | #ifdef MOUSE_ENABLE | 746 | #ifdef MOUSE_ENABLE |
| 775 | bool adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, | 747 | bool adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) { |
| 776 | int8_t pan, uint8_t buttons) { | 748 | struct queue_item item; |
| 777 | struct queue_item item; | 749 | |
| 778 | 750 | item.queue_type = QTMouseMove; | |
| 779 | item.queue_type = QTMouseMove; | 751 | item.mousemove.x = x; |
| 780 | item.mousemove.x = x; | 752 | item.mousemove.y = y; |
| 781 | item.mousemove.y = y; | 753 | item.mousemove.scroll = scroll; |
| 782 | item.mousemove.scroll = scroll; | 754 | item.mousemove.pan = pan; |
| 783 | item.mousemove.pan = pan; | 755 | item.mousemove.buttons = buttons; |
| 784 | item.mousemove.buttons = buttons; | 756 | |
| 785 | 757 | while (!send_buf.enqueue(item)) { | |
| 786 | while (!send_buf.enqueue(item)) { | 758 | send_buf_send_one(); |
| 787 | send_buf_send_one(); | 759 | } |
| 788 | } | 760 | return true; |
| 789 | return true; | ||
| 790 | } | 761 | } |
| 791 | #endif | 762 | #endif |
| 792 | 763 | ||
| 793 | uint32_t adafruit_ble_read_battery_voltage(void) { | 764 | uint32_t adafruit_ble_read_battery_voltage(void) { return state.vbat; } |
| 794 | return state.vbat; | ||
| 795 | } | ||
| 796 | 765 | ||
| 797 | bool adafruit_ble_set_mode_leds(bool on) { | 766 | bool adafruit_ble_set_mode_leds(bool on) { |
| 798 | if (!state.configured) { | 767 | if (!state.configured) { |
| 799 | return false; | 768 | return false; |
| 800 | } | 769 | } |
| 801 | 770 | ||
| 802 | // The "mode" led is the red blinky one | 771 | // The "mode" led is the red blinky one |
| 803 | at_command_P(on ? PSTR("AT+HWMODELED=1") : PSTR("AT+HWMODELED=0"), NULL, 0); | 772 | at_command_P(on ? PSTR("AT+HWMODELED=1") : PSTR("AT+HWMODELED=0"), NULL, 0); |
| 804 | 773 | ||
| 805 | // Pin 19 is the blue "connected" LED; turn that off too. | 774 | // Pin 19 is the blue "connected" LED; turn that off too. |
| 806 | // When turning LEDs back on, don't turn that LED on if we're | 775 | // When turning LEDs back on, don't turn that LED on if we're |
| 807 | // not connected, as that would be confusing. | 776 | // not connected, as that would be confusing. |
| 808 | at_command_P(on && state.is_connected ? PSTR("AT+HWGPIO=19,1") | 777 | at_command_P(on && state.is_connected ? PSTR("AT+HWGPIO=19,1") : PSTR("AT+HWGPIO=19,0"), NULL, 0); |
| 809 | : PSTR("AT+HWGPIO=19,0"), | 778 | return true; |
| 810 | NULL, 0); | ||
| 811 | return true; | ||
| 812 | } | 779 | } |
| 813 | 780 | ||
| 814 | // https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel | 781 | // https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel |
| 815 | bool adafruit_ble_set_power_level(int8_t level) { | 782 | bool adafruit_ble_set_power_level(int8_t level) { |
| 816 | char cmd[46]; | 783 | char cmd[46]; |
| 817 | if (!state.configured) { | 784 | if (!state.configured) { |
| 818 | return false; | 785 | return false; |
| 819 | } | 786 | } |
| 820 | snprintf(cmd, sizeof(cmd), "AT+BLEPOWERLEVEL=%d", level); | 787 | snprintf(cmd, sizeof(cmd), "AT+BLEPOWERLEVEL=%d", level); |
| 821 | return at_command(cmd, NULL, 0, false); | 788 | return at_command(cmd, NULL, 0, false); |
| 822 | } | 789 | } |
diff --git a/tmk_core/protocol/lufa/adafruit_ble.h b/tmk_core/protocol/lufa/adafruit_ble.h index 5d26a9d5a..cef46fe9f 100644 --- a/tmk_core/protocol/lufa/adafruit_ble.h +++ b/tmk_core/protocol/lufa/adafruit_ble.h | |||
| @@ -4,16 +4,16 @@ | |||
| 4 | */ | 4 | */ |
| 5 | #pragma once | 5 | #pragma once |
| 6 | #ifdef MODULE_ADAFRUIT_BLE | 6 | #ifdef MODULE_ADAFRUIT_BLE |
| 7 | #include <stdbool.h> | 7 | # include <stdbool.h> |
| 8 | #include <stdint.h> | 8 | # include <stdint.h> |
| 9 | #include <string.h> | 9 | # include <string.h> |
| 10 | 10 | ||
| 11 | #include "config_common.h" | 11 | # include "config_common.h" |
| 12 | #include "progmem.h" | 12 | # include "progmem.h" |
| 13 | 13 | ||
| 14 | #ifdef __cplusplus | 14 | # ifdef __cplusplus |
| 15 | extern "C" { | 15 | extern "C" { |
| 16 | #endif | 16 | # endif |
| 17 | 17 | ||
| 18 | /* Instruct the module to enable HID keyboard support and reset */ | 18 | /* Instruct the module to enable HID keyboard support and reset */ |
| 19 | extern bool adafruit_ble_enable_keyboard(void); | 19 | extern bool adafruit_ble_enable_keyboard(void); |
| @@ -34,20 +34,18 @@ extern void adafruit_ble_task(void); | |||
| 34 | * this set of keys. | 34 | * this set of keys. |
| 35 | * Also sends a key release indicator, so that the keys do not remain | 35 | * Also sends a key release indicator, so that the keys do not remain |
| 36 | * held down. */ | 36 | * held down. */ |
| 37 | extern bool adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, | 37 | extern bool adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys); |
| 38 | uint8_t nkeys); | ||
| 39 | 38 | ||
| 40 | /* Send a consumer keycode, holding it down for the specified duration | 39 | /* Send a consumer keycode, holding it down for the specified duration |
| 41 | * (milliseconds) */ | 40 | * (milliseconds) */ |
| 42 | extern bool adafruit_ble_send_consumer_key(uint16_t keycode, int hold_duration); | 41 | extern bool adafruit_ble_send_consumer_key(uint16_t keycode, int hold_duration); |
| 43 | 42 | ||
| 44 | #ifdef MOUSE_ENABLE | 43 | # ifdef MOUSE_ENABLE |
| 45 | /* Send a mouse/wheel movement report. | 44 | /* Send a mouse/wheel movement report. |
| 46 | * The parameters are signed and indicate positive of negative direction | 45 | * The parameters are signed and indicate positive of negative direction |
| 47 | * change. */ | 46 | * change. */ |
| 48 | extern bool adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, | 47 | extern bool adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons); |
| 49 | int8_t pan, uint8_t buttons); | 48 | # endif |
| 50 | #endif | ||
| 51 | 49 | ||
| 52 | /* Compute battery voltage by reading an analog pin. | 50 | /* Compute battery voltage by reading an analog pin. |
| 53 | * Returns the integer number of millivolts */ | 51 | * Returns the integer number of millivolts */ |
| @@ -56,8 +54,8 @@ extern uint32_t adafruit_ble_read_battery_voltage(void); | |||
| 56 | extern bool adafruit_ble_set_mode_leds(bool on); | 54 | extern bool adafruit_ble_set_mode_leds(bool on); |
| 57 | extern bool adafruit_ble_set_power_level(int8_t level); | 55 | extern bool adafruit_ble_set_power_level(int8_t level); |
| 58 | 56 | ||
| 59 | #ifdef __cplusplus | 57 | # ifdef __cplusplus |
| 60 | } | 58 | } |
| 61 | #endif | 59 | # endif |
| 62 | 60 | ||
| 63 | #endif // MODULE_ADAFRUIT_BLE | 61 | #endif // MODULE_ADAFRUIT_BLE |
diff --git a/tmk_core/protocol/lufa/bluetooth.c b/tmk_core/protocol/lufa/bluetooth.c index 549606162..5eb52860b 100644 --- a/tmk_core/protocol/lufa/bluetooth.c +++ b/tmk_core/protocol/lufa/bluetooth.c | |||
| @@ -21,16 +21,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 21 | #include "debug.h" | 21 | #include "debug.h" |
| 22 | #include "bluetooth.h" | 22 | #include "bluetooth.h" |
| 23 | 23 | ||
| 24 | void bluefruit_keyboard_print_report(report_keyboard_t *report) | 24 | void bluefruit_keyboard_print_report(report_keyboard_t *report) { |
| 25 | { | ||
| 26 | if (!debug_keyboard) return; | 25 | if (!debug_keyboard) return; |
| 27 | dprintf("keys: "); for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); } | 26 | dprintf("keys: "); |
| 28 | dprintf(" mods: "); debug_hex8(report->mods); | 27 | for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { |
| 29 | dprintf(" reserved: "); debug_hex8(report->reserved); | 28 | debug_hex8(report->keys[i]); |
| 29 | dprintf(" "); | ||
| 30 | } | ||
| 31 | dprintf(" mods: "); | ||
| 32 | debug_hex8(report->mods); | ||
| 33 | dprintf(" reserved: "); | ||
| 34 | debug_hex8(report->reserved); | ||
| 30 | dprintf("\n"); | 35 | dprintf("\n"); |
| 31 | } | 36 | } |
| 32 | 37 | ||
| 33 | void bluefruit_serial_send(uint8_t data) | 38 | void bluefruit_serial_send(uint8_t data) { serial_send(data); } \ No newline at end of file |
| 34 | { | ||
| 35 | serial_send(data); | ||
| 36 | } \ No newline at end of file | ||
diff --git a/tmk_core/protocol/lufa/bluetooth.h b/tmk_core/protocol/lufa/bluetooth.h index f4b2f6f8b..081271a4e 100644 --- a/tmk_core/protocol/lufa/bluetooth.h +++ b/tmk_core/protocol/lufa/bluetooth.h | |||
| @@ -41,39 +41,8 @@ void bluefruit_serial_send(uint8_t data); | |||
| 41 | | Stop | 00000000 00010000 | 00 10 | | 41 | | Stop | 00000000 00010000 | 00 10 | |
| 42 | +-------------------------------------+-------+ | 42 | +-------------------------------------+-------+ |
| 43 | */ | 43 | */ |
| 44 | #define CONSUMER2BLUEFRUIT(usage) \ | 44 | #define CONSUMER2BLUEFRUIT(usage) (usage == AUDIO_MUTE ? 0x0000 : (usage == AUDIO_VOL_UP ? 0x1000 : (usage == AUDIO_VOL_DOWN ? 0x2000 : (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : (usage == TRANSPORT_PREV_TRACK ? 0x0004 : (usage == TRANSPORT_STOP ? 0x0010 : (usage == TRANSPORT_STOP_EJECT ? 0x0000 : (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : (usage == AL_CC_CONFIG ? 0x0000 : (usage == AL_EMAIL ? 0x0000 : (usage == AL_CALCULATOR ? 0x0000 : (usage == AL_LOCAL_BROWSER ? 0x0000 : (usage == AC_SEARCH ? 0x0400 : (usage == AC_HOME ? 0x0100 : (usage == AC_BACK ? 0x0000 : (usage == AC_FORWARD ? 0x0000 : (usage == AC_STOP ? 0x0000 : (usage == AC_REFRESH ? 0x0000 : (usage == AC_BOOKMARKS ? 0x0000 : 0))))))))))))))))))) |
| 45 | (usage == AUDIO_MUTE ? 0x0000 : \ | ||
| 46 | (usage == AUDIO_VOL_UP ? 0x1000 : \ | ||
| 47 | (usage == AUDIO_VOL_DOWN ? 0x2000 : \ | ||
| 48 | (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : \ | ||
| 49 | (usage == TRANSPORT_PREV_TRACK ? 0x0004 : \ | ||
| 50 | (usage == TRANSPORT_STOP ? 0x0010 : \ | ||
| 51 | (usage == TRANSPORT_STOP_EJECT ? 0x0000 : \ | ||
| 52 | (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : \ | ||
| 53 | (usage == AL_CC_CONFIG ? 0x0000 : \ | ||
| 54 | (usage == AL_EMAIL ? 0x0000 : \ | ||
| 55 | (usage == AL_CALCULATOR ? 0x0000 : \ | ||
| 56 | (usage == AL_LOCAL_BROWSER ? 0x0000 : \ | ||
| 57 | (usage == AC_SEARCH ? 0x0400 : \ | ||
| 58 | (usage == AC_HOME ? 0x0100 : \ | ||
| 59 | (usage == AC_BACK ? 0x0000 : \ | ||
| 60 | (usage == AC_FORWARD ? 0x0000 : \ | ||
| 61 | (usage == AC_STOP ? 0x0000 : \ | ||
| 62 | (usage == AC_REFRESH ? 0x0000 : \ | ||
| 63 | (usage == AC_BOOKMARKS ? 0x0000 : 0))))))))))))))))))) | ||
| 64 | 45 | ||
| 65 | #define CONSUMER2RN42(usage) \ | 46 | #define CONSUMER2RN42(usage) (usage == AUDIO_MUTE ? 0x0040 : (usage == AUDIO_VOL_UP ? 0x0010 : (usage == AUDIO_VOL_DOWN ? 0x0020 : (usage == TRANSPORT_NEXT_TRACK ? 0x0100 : (usage == TRANSPORT_PREV_TRACK ? 0x0200 : (usage == TRANSPORT_STOP ? 0x0400 : (usage == TRANSPORT_STOP_EJECT ? 0x0800 : (usage == TRANSPORT_PLAY_PAUSE ? 0x0080 : (usage == AL_EMAIL ? 0x0200 : (usage == AL_LOCAL_BROWSER ? 0x8000 : (usage == AC_SEARCH ? 0x0400 : (usage == AC_HOME ? 0x0100 : 0)))))))))))) |
| 66 | (usage == AUDIO_MUTE ? 0x0040 : \ | ||
| 67 | (usage == AUDIO_VOL_UP ? 0x0010 : \ | ||
| 68 | (usage == AUDIO_VOL_DOWN ? 0x0020 : \ | ||
| 69 | (usage == TRANSPORT_NEXT_TRACK ? 0x0100 : \ | ||
| 70 | (usage == TRANSPORT_PREV_TRACK ? 0x0200 : \ | ||
| 71 | (usage == TRANSPORT_STOP ? 0x0400 : \ | ||
| 72 | (usage == TRANSPORT_STOP_EJECT ? 0x0800 : \ | ||
| 73 | (usage == TRANSPORT_PLAY_PAUSE ? 0x0080 : \ | ||
| 74 | (usage == AL_EMAIL ? 0x0200 : \ | ||
| 75 | (usage == AL_LOCAL_BROWSER ? 0x8000 : \ | ||
| 76 | (usage == AC_SEARCH ? 0x0400 : \ | ||
| 77 | (usage == AC_HOME ? 0x0100 : 0)))))))))))) | ||
| 78 | 47 | ||
| 79 | #endif | 48 | #endif |
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index f2ecf2465..12a6924fd 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | #include "sendchar.h" | 45 | #include "sendchar.h" |
| 46 | #include "debug.h" | 46 | #include "debug.h" |
| 47 | #ifdef SLEEP_LED_ENABLE | 47 | #ifdef SLEEP_LED_ENABLE |
| 48 | #include "sleep_led.h" | 48 | # include "sleep_led.h" |
| 49 | #endif | 49 | #endif |
| 50 | #include "suspend.h" | 50 | #include "suspend.h" |
| 51 | 51 | ||
| @@ -57,86 +57,80 @@ | |||
| 57 | #include "rgblight_reconfig.h" | 57 | #include "rgblight_reconfig.h" |
| 58 | 58 | ||
| 59 | #ifdef NKRO_ENABLE | 59 | #ifdef NKRO_ENABLE |
| 60 | #include "keycode_config.h" | 60 | # include "keycode_config.h" |
| 61 | 61 | ||
| 62 | extern keymap_config_t keymap_config; | 62 | extern keymap_config_t keymap_config; |
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | |||
| 66 | #ifdef AUDIO_ENABLE | 65 | #ifdef AUDIO_ENABLE |
| 67 | #include <audio.h> | 66 | # include <audio.h> |
| 68 | #endif | 67 | #endif |
| 69 | 68 | ||
| 70 | #ifdef BLUETOOTH_ENABLE | 69 | #ifdef BLUETOOTH_ENABLE |
| 71 | #ifdef MODULE_ADAFRUIT_BLE | 70 | # ifdef MODULE_ADAFRUIT_BLE |
| 72 | #include "adafruit_ble.h" | 71 | # include "adafruit_ble.h" |
| 73 | #else | 72 | # else |
| 74 | #include "bluetooth.h" | 73 | # include "bluetooth.h" |
| 75 | #endif | 74 | # endif |
| 76 | #endif | 75 | #endif |
| 77 | 76 | ||
| 78 | #ifdef VIRTSER_ENABLE | 77 | #ifdef VIRTSER_ENABLE |
| 79 | #include "virtser.h" | 78 | # include "virtser.h" |
| 80 | #endif | 79 | #endif |
| 81 | 80 | ||
| 82 | #if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE) | 81 | #if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE) |
| 83 | #include "rgblight.h" | 82 | # include "rgblight.h" |
| 84 | #endif | 83 | #endif |
| 85 | 84 | ||
| 86 | #ifdef MIDI_ENABLE | 85 | #ifdef MIDI_ENABLE |
| 87 | #include "qmk_midi.h" | 86 | # include "qmk_midi.h" |
| 88 | #endif | 87 | #endif |
| 89 | 88 | ||
| 90 | #ifdef RAW_ENABLE | 89 | #ifdef RAW_ENABLE |
| 91 | #include "raw_hid.h" | 90 | # include "raw_hid.h" |
| 92 | #endif | 91 | #endif |
| 93 | 92 | ||
| 94 | uint8_t keyboard_idle = 0; | 93 | uint8_t keyboard_idle = 0; |
| 95 | /* 0: Boot Protocol, 1: Report Protocol(default) */ | 94 | /* 0: Boot Protocol, 1: Report Protocol(default) */ |
| 96 | uint8_t keyboard_protocol = 1; | 95 | uint8_t keyboard_protocol = 1; |
| 97 | static uint8_t keyboard_led_stats = 0; | 96 | static uint8_t keyboard_led_stats = 0; |
| 98 | 97 | ||
| 99 | static report_keyboard_t keyboard_report_sent; | 98 | static report_keyboard_t keyboard_report_sent; |
| 100 | 99 | ||
| 101 | /* Host driver */ | 100 | /* Host driver */ |
| 102 | static uint8_t keyboard_leds(void); | 101 | static uint8_t keyboard_leds(void); |
| 103 | static void send_keyboard(report_keyboard_t *report); | 102 | static void send_keyboard(report_keyboard_t *report); |
| 104 | static void send_mouse(report_mouse_t *report); | 103 | static void send_mouse(report_mouse_t *report); |
| 105 | static void send_system(uint16_t data); | 104 | static void send_system(uint16_t data); |
| 106 | static void send_consumer(uint16_t data); | 105 | static void send_consumer(uint16_t data); |
| 107 | host_driver_t lufa_driver = { | 106 | host_driver_t lufa_driver = { |
| 108 | keyboard_leds, | 107 | keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, |
| 109 | send_keyboard, | ||
| 110 | send_mouse, | ||
| 111 | send_system, | ||
| 112 | send_consumer, | ||
| 113 | }; | 108 | }; |
| 114 | 109 | ||
| 115 | #ifdef VIRTSER_ENABLE | 110 | #ifdef VIRTSER_ENABLE |
| 116 | USB_ClassInfo_CDC_Device_t cdc_device = | 111 | USB_ClassInfo_CDC_Device_t cdc_device = { |
| 117 | { | 112 | .Config = |
| 118 | .Config = | 113 | { |
| 119 | { | 114 | .ControlInterfaceNumber = CCI_INTERFACE, |
| 120 | .ControlInterfaceNumber = CCI_INTERFACE, | 115 | .DataINEndpoint = |
| 121 | .DataINEndpoint = | 116 | { |
| 122 | { | 117 | .Address = CDC_IN_EPADDR, |
| 123 | .Address = CDC_IN_EPADDR, | 118 | .Size = CDC_EPSIZE, |
| 124 | .Size = CDC_EPSIZE, | 119 | .Banks = 1, |
| 125 | .Banks = 1, | 120 | }, |
| 126 | }, | 121 | .DataOUTEndpoint = |
| 127 | .DataOUTEndpoint = | 122 | { |
| 128 | { | 123 | .Address = CDC_OUT_EPADDR, |
| 129 | .Address = CDC_OUT_EPADDR, | 124 | .Size = CDC_EPSIZE, |
| 130 | .Size = CDC_EPSIZE, | 125 | .Banks = 1, |
| 131 | .Banks = 1, | 126 | }, |
| 132 | }, | 127 | .NotificationEndpoint = |
| 133 | .NotificationEndpoint = | 128 | { |
| 134 | { | 129 | .Address = CDC_NOTIFICATION_EPADDR, |
| 135 | .Address = CDC_NOTIFICATION_EPADDR, | 130 | .Size = CDC_NOTIFICATION_EPSIZE, |
| 136 | .Size = CDC_NOTIFICATION_EPSIZE, | 131 | .Banks = 1, |
| 137 | .Banks = 1, | 132 | }, |
| 138 | }, | 133 | }, |
| 139 | }, | ||
| 140 | }; | 134 | }; |
| 141 | #endif | 135 | #endif |
| 142 | 136 | ||
| @@ -146,84 +140,73 @@ USB_ClassInfo_CDC_Device_t cdc_device = | |||
| 146 | * | 140 | * |
| 147 | * FIXME: Needs doc | 141 | * FIXME: Needs doc |
| 148 | */ | 142 | */ |
| 149 | void raw_hid_send( uint8_t *data, uint8_t length ) | 143 | void raw_hid_send(uint8_t *data, uint8_t length) { |
| 150 | { | 144 | // TODO: implement variable size packet |
| 151 | // TODO: implement variable size packet | 145 | if (length != RAW_EPSIZE) { |
| 152 | if ( length != RAW_EPSIZE ) | 146 | return; |
| 153 | { | 147 | } |
| 154 | return; | 148 | |
| 155 | } | 149 | if (USB_DeviceState != DEVICE_STATE_Configured) { |
| 156 | 150 | return; | |
| 157 | if (USB_DeviceState != DEVICE_STATE_Configured) | 151 | } |
| 158 | { | 152 | |
| 159 | return; | 153 | // TODO: decide if we allow calls to raw_hid_send() in the middle |
| 160 | } | 154 | // of other endpoint usage. |
| 161 | 155 | uint8_t ep = Endpoint_GetCurrentEndpoint(); | |
| 162 | // TODO: decide if we allow calls to raw_hid_send() in the middle | 156 | |
| 163 | // of other endpoint usage. | 157 | Endpoint_SelectEndpoint(RAW_IN_EPNUM); |
| 164 | uint8_t ep = Endpoint_GetCurrentEndpoint(); | 158 | |
| 165 | 159 | // Check to see if the host is ready to accept another packet | |
| 166 | Endpoint_SelectEndpoint(RAW_IN_EPNUM); | 160 | if (Endpoint_IsINReady()) { |
| 167 | 161 | // Write data | |
| 168 | // Check to see if the host is ready to accept another packet | 162 | Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL); |
| 169 | if (Endpoint_IsINReady()) | 163 | // Finalize the stream transfer to send the last packet |
| 170 | { | 164 | Endpoint_ClearIN(); |
| 171 | // Write data | 165 | } |
| 172 | Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL); | 166 | |
| 173 | // Finalize the stream transfer to send the last packet | 167 | Endpoint_SelectEndpoint(ep); |
| 174 | Endpoint_ClearIN(); | ||
| 175 | } | ||
| 176 | |||
| 177 | Endpoint_SelectEndpoint(ep); | ||
| 178 | } | 168 | } |
| 179 | 169 | ||
| 180 | /** \brief Raw HID Receive | 170 | /** \brief Raw HID Receive |
| 181 | * | 171 | * |
| 182 | * FIXME: Needs doc | 172 | * FIXME: Needs doc |
| 183 | */ | 173 | */ |
| 184 | __attribute__ ((weak)) | 174 | __attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { |
| 185 | void raw_hid_receive( uint8_t *data, uint8_t length ) | 175 | // Users should #include "raw_hid.h" in their own code |
| 186 | { | 176 | // and implement this function there. Leave this as weak linkage |
| 187 | // Users should #include "raw_hid.h" in their own code | 177 | // so users can opt to not handle data coming in. |
| 188 | // and implement this function there. Leave this as weak linkage | ||
| 189 | // so users can opt to not handle data coming in. | ||
| 190 | } | 178 | } |
| 191 | 179 | ||
| 192 | /** \brief Raw HID Task | 180 | /** \brief Raw HID Task |
| 193 | * | 181 | * |
| 194 | * FIXME: Needs doc | 182 | * FIXME: Needs doc |
| 195 | */ | 183 | */ |
| 196 | static void raw_hid_task(void) | 184 | static void raw_hid_task(void) { |
| 197 | { | 185 | // Create a temporary buffer to hold the read in data from the host |
| 198 | // Create a temporary buffer to hold the read in data from the host | 186 | uint8_t data[RAW_EPSIZE]; |
| 199 | uint8_t data[RAW_EPSIZE]; | 187 | bool data_read = false; |
| 200 | bool data_read = false; | 188 | |
| 201 | 189 | // Device must be connected and configured for the task to run | |
| 202 | // Device must be connected and configured for the task to run | 190 | if (USB_DeviceState != DEVICE_STATE_Configured) return; |
| 203 | if (USB_DeviceState != DEVICE_STATE_Configured) | 191 | |
| 204 | return; | 192 | Endpoint_SelectEndpoint(RAW_OUT_EPNUM); |
| 205 | 193 | ||
| 206 | Endpoint_SelectEndpoint(RAW_OUT_EPNUM); | 194 | // Check to see if a packet has been sent from the host |
| 207 | 195 | if (Endpoint_IsOUTReceived()) { | |
| 208 | // Check to see if a packet has been sent from the host | 196 | // Check to see if the packet contains data |
| 209 | if (Endpoint_IsOUTReceived()) | 197 | if (Endpoint_IsReadWriteAllowed()) { |
| 210 | { | 198 | /* Read data */ |
| 211 | // Check to see if the packet contains data | 199 | Endpoint_Read_Stream_LE(data, sizeof(data), NULL); |
| 212 | if (Endpoint_IsReadWriteAllowed()) | 200 | data_read = true; |
| 213 | { | 201 | } |
| 214 | /* Read data */ | 202 | |
| 215 | Endpoint_Read_Stream_LE(data, sizeof(data), NULL); | 203 | // Finalize the stream transfer to receive the last packet |
| 216 | data_read = true; | 204 | Endpoint_ClearOUT(); |
| 217 | } | 205 | |
| 218 | 206 | if (data_read) { | |
| 219 | // Finalize the stream transfer to receive the last packet | 207 | raw_hid_receive(data, sizeof(data)); |
| 220 | Endpoint_ClearOUT(); | 208 | } |
| 221 | 209 | } | |
| 222 | if ( data_read ) | ||
| 223 | { | ||
| 224 | raw_hid_receive( data, sizeof(data) ); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | } | 210 | } |
| 228 | #endif | 211 | #endif |
| 229 | 212 | ||
| @@ -235,15 +218,13 @@ static void raw_hid_task(void) | |||
| 235 | * | 218 | * |
| 236 | * FIXME: Needs doc | 219 | * FIXME: Needs doc |
| 237 | */ | 220 | */ |
| 238 | static void Console_Task(void) | 221 | static void Console_Task(void) { |
| 239 | { | ||
| 240 | /* Device must be connected and configured for the task to run */ | 222 | /* Device must be connected and configured for the task to run */ |
| 241 | if (USB_DeviceState != DEVICE_STATE_Configured) | 223 | if (USB_DeviceState != DEVICE_STATE_Configured) return; |
| 242 | return; | ||
| 243 | 224 | ||
| 244 | uint8_t ep = Endpoint_GetCurrentEndpoint(); | 225 | uint8_t ep = Endpoint_GetCurrentEndpoint(); |
| 245 | 226 | ||
| 246 | #if 0 | 227 | # if 0 |
| 247 | // TODO: impl receivechar()/recvchar() | 228 | // TODO: impl receivechar()/recvchar() |
| 248 | Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM); | 229 | Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM); |
| 249 | 230 | ||
| @@ -266,7 +247,7 @@ static void Console_Task(void) | |||
| 266 | /* Finalize the stream transfer to send the last packet */ | 247 | /* Finalize the stream transfer to send the last packet */ |
| 267 | Endpoint_ClearOUT(); | 248 | Endpoint_ClearOUT(); |
| 268 | } | 249 | } |
| 269 | #endif | 250 | # endif |
| 270 | 251 | ||
| 271 | /* IN packet */ | 252 | /* IN packet */ |
| 272 | Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); | 253 | Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); |
| @@ -276,8 +257,7 @@ static void Console_Task(void) | |||
| 276 | } | 257 | } |
| 277 | 258 | ||
| 278 | // fill empty bank | 259 | // fill empty bank |
| 279 | while (Endpoint_IsReadWriteAllowed()) | 260 | while (Endpoint_IsReadWriteAllowed()) Endpoint_Write_8(0); |
| 280 | Endpoint_Write_8(0); | ||
| 281 | 261 | ||
| 282 | // flash senchar packet | 262 | // flash senchar packet |
| 283 | if (Endpoint_IsINReady()) { | 263 | if (Endpoint_IsINReady()) { |
| @@ -288,7 +268,6 @@ static void Console_Task(void) | |||
| 288 | } | 268 | } |
| 289 | #endif | 269 | #endif |
| 290 | 270 | ||
| 291 | |||
| 292 | /******************************************************************************* | 271 | /******************************************************************************* |
| 293 | * USB Events | 272 | * USB Events |
| 294 | ******************************************************************************/ | 273 | ******************************************************************************/ |
| @@ -298,13 +277,12 @@ static void Console_Task(void) | |||
| 298 | * 1) EVENT_USB_Device_Suspend | 277 | * 1) EVENT_USB_Device_Suspend |
| 299 | * 2) EVENT_USB_Device_Reset | 278 | * 2) EVENT_USB_Device_Reset |
| 300 | * 3) EVENT_USB_Device_Wake | 279 | * 3) EVENT_USB_Device_Wake |
| 301 | */ | 280 | */ |
| 302 | /** \brief Event USB Device Connect | 281 | /** \brief Event USB Device Connect |
| 303 | * | 282 | * |
| 304 | * FIXME: Needs doc | 283 | * FIXME: Needs doc |
| 305 | */ | 284 | */ |
| 306 | void EVENT_USB_Device_Connect(void) | 285 | void EVENT_USB_Device_Connect(void) { |
| 307 | { | ||
| 308 | print("[C]"); | 286 | print("[C]"); |
| 309 | /* For battery powered device */ | 287 | /* For battery powered device */ |
| 310 | if (!USB_IsInitialized) { | 288 | if (!USB_IsInitialized) { |
| @@ -318,35 +296,30 @@ void EVENT_USB_Device_Connect(void) | |||
| 318 | * | 296 | * |
| 319 | * FIXME: Needs doc | 297 | * FIXME: Needs doc |
| 320 | */ | 298 | */ |
| 321 | void EVENT_USB_Device_Disconnect(void) | 299 | void EVENT_USB_Device_Disconnect(void) { |
| 322 | { | ||
| 323 | print("[D]"); | 300 | print("[D]"); |
| 324 | /* For battery powered device */ | 301 | /* For battery powered device */ |
| 325 | USB_IsInitialized = false; | 302 | USB_IsInitialized = false; |
| 326 | /* TODO: This doesn't work. After several plug in/outs can not be enumerated. | 303 | /* TODO: This doesn't work. After several plug in/outs can not be enumerated. |
| 327 | if (USB_IsInitialized) { | 304 | if (USB_IsInitialized) { |
| 328 | USB_Disable(); // Disable all interrupts | 305 | USB_Disable(); // Disable all interrupts |
| 329 | USB_Controller_Enable(); | 306 | USB_Controller_Enable(); |
| 330 | USB_INT_Enable(USB_INT_VBUSTI); | 307 | USB_INT_Enable(USB_INT_VBUSTI); |
| 331 | } | 308 | } |
| 332 | */ | 309 | */ |
| 333 | } | 310 | } |
| 334 | 311 | ||
| 335 | /** \brief Event USB Device Connect | 312 | /** \brief Event USB Device Connect |
| 336 | * | 313 | * |
| 337 | * FIXME: Needs doc | 314 | * FIXME: Needs doc |
| 338 | */ | 315 | */ |
| 339 | void EVENT_USB_Device_Reset(void) | 316 | void EVENT_USB_Device_Reset(void) { print("[R]"); } |
| 340 | { | ||
| 341 | print("[R]"); | ||
| 342 | } | ||
| 343 | 317 | ||
| 344 | /** \brief Event USB Device Connect | 318 | /** \brief Event USB Device Connect |
| 345 | * | 319 | * |
| 346 | * FIXME: Needs doc | 320 | * FIXME: Needs doc |
| 347 | */ | 321 | */ |
| 348 | void EVENT_USB_Device_Suspend() | 322 | void EVENT_USB_Device_Suspend() { |
| 349 | { | ||
| 350 | print("[S]"); | 323 | print("[S]"); |
| 351 | #ifdef SLEEP_LED_ENABLE | 324 | #ifdef SLEEP_LED_ENABLE |
| 352 | sleep_led_enable(); | 325 | sleep_led_enable(); |
| @@ -357,8 +330,7 @@ void EVENT_USB_Device_Suspend() | |||
| 357 | * | 330 | * |
| 358 | * FIXME: Needs doc | 331 | * FIXME: Needs doc |
| 359 | */ | 332 | */ |
| 360 | void EVENT_USB_Device_WakeUp() | 333 | void EVENT_USB_Device_WakeUp() { |
| 361 | { | ||
| 362 | print("[W]"); | 334 | print("[W]"); |
| 363 | suspend_wakeup_init(); | 335 | suspend_wakeup_init(); |
| 364 | 336 | ||
| @@ -369,23 +341,19 @@ void EVENT_USB_Device_WakeUp() | |||
| 369 | #endif | 341 | #endif |
| 370 | } | 342 | } |
| 371 | 343 | ||
| 372 | |||
| 373 | |||
| 374 | #ifdef CONSOLE_ENABLE | 344 | #ifdef CONSOLE_ENABLE |
| 375 | static bool console_flush = false; | 345 | static bool console_flush = false; |
| 376 | #define CONSOLE_FLUSH_SET(b) do { \ | 346 | # define CONSOLE_FLUSH_SET(b) \ |
| 377 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {\ | 347 | do { \ |
| 378 | console_flush = b; \ | 348 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { console_flush = b; } \ |
| 379 | } \ | 349 | } while (0) |
| 380 | } while (0) | ||
| 381 | 350 | ||
| 382 | /** \brief Event USB Device Start Of Frame | 351 | /** \brief Event USB Device Start Of Frame |
| 383 | * | 352 | * |
| 384 | * FIXME: Needs doc | 353 | * FIXME: Needs doc |
| 385 | * called every 1ms | 354 | * called every 1ms |
| 386 | */ | 355 | */ |
| 387 | void EVENT_USB_Device_StartOfFrame(void) | 356 | void EVENT_USB_Device_StartOfFrame(void) { |
| 388 | { | ||
| 389 | static uint8_t count; | 357 | static uint8_t count; |
| 390 | if (++count % 50) return; | 358 | if (++count % 50) return; |
| 391 | count = 0; | 359 | count = 0; |
| @@ -404,44 +372,37 @@ void EVENT_USB_Device_StartOfFrame(void) | |||
| 404 | * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4, | 372 | * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4, |
| 405 | * it is safe to use single bank for all endpoints. | 373 | * it is safe to use single bank for all endpoints. |
| 406 | */ | 374 | */ |
| 407 | void EVENT_USB_Device_ConfigurationChanged(void) | 375 | void EVENT_USB_Device_ConfigurationChanged(void) { |
| 408 | { | ||
| 409 | bool ConfigSuccess = true; | 376 | bool ConfigSuccess = true; |
| 410 | 377 | ||
| 411 | /* Setup Keyboard HID Report Endpoints */ | 378 | /* Setup Keyboard HID Report Endpoints */ |
| 412 | #ifndef KEYBOARD_SHARED_EP | 379 | #ifndef KEYBOARD_SHARED_EP |
| 413 | ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 380 | ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 414 | KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 415 | #endif | 381 | #endif |
| 416 | 382 | ||
| 417 | #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP) | 383 | #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP) |
| 418 | /* Setup Mouse HID Report Endpoint */ | 384 | /* Setup Mouse HID Report Endpoint */ |
| 419 | ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 385 | ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 420 | MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 421 | #endif | 386 | #endif |
| 422 | 387 | ||
| 423 | #ifdef SHARED_EP_ENABLE | 388 | #ifdef SHARED_EP_ENABLE |
| 424 | /* Setup Shared HID Report Endpoint */ | 389 | /* Setup Shared HID Report Endpoint */ |
| 425 | ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 390 | ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, SHARED_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 426 | SHARED_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 427 | #endif | 391 | #endif |
| 428 | 392 | ||
| 429 | #ifdef RAW_ENABLE | 393 | #ifdef RAW_ENABLE |
| 430 | /* Setup Raw HID Report Endpoints */ | 394 | /* Setup Raw HID Report Endpoints */ |
| 431 | ConfigSuccess &= ENDPOINT_CONFIG(RAW_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 395 | ConfigSuccess &= ENDPOINT_CONFIG(RAW_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, RAW_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 432 | RAW_EPSIZE, ENDPOINT_BANK_SINGLE); | 396 | ConfigSuccess &= ENDPOINT_CONFIG(RAW_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, RAW_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 433 | ConfigSuccess &= ENDPOINT_CONFIG(RAW_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | ||
| 434 | RAW_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 435 | #endif | 397 | #endif |
| 436 | 398 | ||
| 437 | #ifdef CONSOLE_ENABLE | 399 | #ifdef CONSOLE_ENABLE |
| 438 | /* Setup Console HID Report Endpoints */ | 400 | /* Setup Console HID Report Endpoints */ |
| 439 | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 401 | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 440 | CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | 402 | # if 0 |
| 441 | #if 0 | ||
| 442 | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, | 403 | ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT, |
| 443 | CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); | 404 | CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 444 | #endif | 405 | # endif |
| 445 | #endif | 406 | #endif |
| 446 | 407 | ||
| 447 | #ifdef MIDI_ENABLE | 408 | #ifdef MIDI_ENABLE |
| @@ -473,26 +434,23 @@ Other Device Required Optional Optional Optional Optional Opti | |||
| 473 | * | 434 | * |
| 474 | * This is fired before passing along unhandled control requests to the library for processing internally. | 435 | * This is fired before passing along unhandled control requests to the library for processing internally. |
| 475 | */ | 436 | */ |
| 476 | void EVENT_USB_Device_ControlRequest(void) | 437 | void EVENT_USB_Device_ControlRequest(void) { |
| 477 | { | 438 | uint8_t *ReportData = NULL; |
| 478 | uint8_t* ReportData = NULL; | ||
| 479 | uint8_t ReportSize = 0; | 439 | uint8_t ReportSize = 0; |
| 480 | 440 | ||
| 481 | /* Handle HID Class specific requests */ | 441 | /* Handle HID Class specific requests */ |
| 482 | switch (USB_ControlRequest.bRequest) | 442 | switch (USB_ControlRequest.bRequest) { |
| 483 | { | ||
| 484 | case HID_REQ_GetReport: | 443 | case HID_REQ_GetReport: |
| 485 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | 444 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 486 | { | ||
| 487 | Endpoint_ClearSETUP(); | 445 | Endpoint_ClearSETUP(); |
| 488 | 446 | ||
| 489 | // Interface | 447 | // Interface |
| 490 | switch (USB_ControlRequest.wIndex) { | 448 | switch (USB_ControlRequest.wIndex) { |
| 491 | case KEYBOARD_INTERFACE: | 449 | case KEYBOARD_INTERFACE: |
| 492 | // TODO: test/check | 450 | // TODO: test/check |
| 493 | ReportData = (uint8_t*)&keyboard_report_sent; | 451 | ReportData = (uint8_t *)&keyboard_report_sent; |
| 494 | ReportSize = sizeof(keyboard_report_sent); | 452 | ReportSize = sizeof(keyboard_report_sent); |
| 495 | break; | 453 | break; |
| 496 | } | 454 | } |
| 497 | 455 | ||
| 498 | /* Write the report data to the control endpoint */ | 456 | /* Write the report data to the control endpoint */ |
| @@ -502,47 +460,43 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 502 | 460 | ||
| 503 | break; | 461 | break; |
| 504 | case HID_REQ_SetReport: | 462 | case HID_REQ_SetReport: |
| 505 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | 463 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 506 | { | ||
| 507 | |||
| 508 | // Interface | 464 | // Interface |
| 509 | switch (USB_ControlRequest.wIndex) { | 465 | switch (USB_ControlRequest.wIndex) { |
| 510 | case KEYBOARD_INTERFACE: | 466 | case KEYBOARD_INTERFACE: |
| 511 | #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP) | 467 | #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP) |
| 512 | case SHARED_INTERFACE: | 468 | case SHARED_INTERFACE: |
| 513 | #endif | 469 | #endif |
| 514 | Endpoint_ClearSETUP(); | 470 | Endpoint_ClearSETUP(); |
| 515 | 471 | ||
| 516 | while (!(Endpoint_IsOUTReceived())) { | 472 | while (!(Endpoint_IsOUTReceived())) { |
| 517 | if (USB_DeviceState == DEVICE_STATE_Unattached) | 473 | if (USB_DeviceState == DEVICE_STATE_Unattached) return; |
| 518 | return; | 474 | } |
| 519 | } | ||
| 520 | 475 | ||
| 521 | if (Endpoint_BytesInEndpoint() == 2) { | 476 | if (Endpoint_BytesInEndpoint() == 2) { |
| 522 | uint8_t report_id = Endpoint_Read_8(); | 477 | uint8_t report_id = Endpoint_Read_8(); |
| 523 | 478 | ||
| 524 | if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) { | 479 | if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) { |
| 525 | keyboard_led_stats = Endpoint_Read_8(); | 480 | keyboard_led_stats = Endpoint_Read_8(); |
| 526 | } | 481 | } |
| 527 | } else { | 482 | } else { |
| 528 | keyboard_led_stats = Endpoint_Read_8(); | 483 | keyboard_led_stats = Endpoint_Read_8(); |
| 529 | } | 484 | } |
| 530 | 485 | ||
| 531 | Endpoint_ClearOUT(); | 486 | Endpoint_ClearOUT(); |
| 532 | Endpoint_ClearStatusStage(); | 487 | Endpoint_ClearStatusStage(); |
| 533 | break; | 488 | break; |
| 534 | } | 489 | } |
| 535 | |||
| 536 | } | 490 | } |
| 537 | 491 | ||
| 538 | break; | 492 | break; |
| 539 | 493 | ||
| 540 | case HID_REQ_GetProtocol: | 494 | case HID_REQ_GetProtocol: |
| 541 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | 495 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 542 | { | ||
| 543 | if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | 496 | if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { |
| 544 | Endpoint_ClearSETUP(); | 497 | Endpoint_ClearSETUP(); |
| 545 | while (!(Endpoint_IsINReady())); | 498 | while (!(Endpoint_IsINReady())) |
| 499 | ; | ||
| 546 | Endpoint_Write_8(keyboard_protocol); | 500 | Endpoint_Write_8(keyboard_protocol); |
| 547 | Endpoint_ClearIN(); | 501 | Endpoint_ClearIN(); |
| 548 | Endpoint_ClearStatusStage(); | 502 | Endpoint_ClearStatusStage(); |
| @@ -551,8 +505,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 551 | 505 | ||
| 552 | break; | 506 | break; |
| 553 | case HID_REQ_SetProtocol: | 507 | case HID_REQ_SetProtocol: |
| 554 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | 508 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 555 | { | ||
| 556 | if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | 509 | if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { |
| 557 | Endpoint_ClearSETUP(); | 510 | Endpoint_ClearSETUP(); |
| 558 | Endpoint_ClearStatusStage(); | 511 | Endpoint_ClearStatusStage(); |
| @@ -564,8 +517,7 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 564 | 517 | ||
| 565 | break; | 518 | break; |
| 566 | case HID_REQ_SetIdle: | 519 | case HID_REQ_SetIdle: |
| 567 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | 520 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 568 | { | ||
| 569 | Endpoint_ClearSETUP(); | 521 | Endpoint_ClearSETUP(); |
| 570 | Endpoint_ClearStatusStage(); | 522 | Endpoint_ClearStatusStage(); |
| 571 | 523 | ||
| @@ -574,10 +526,10 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 574 | 526 | ||
| 575 | break; | 527 | break; |
| 576 | case HID_REQ_GetIdle: | 528 | case HID_REQ_GetIdle: |
| 577 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | 529 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { |
| 578 | { | ||
| 579 | Endpoint_ClearSETUP(); | 530 | Endpoint_ClearSETUP(); |
| 580 | while (!(Endpoint_IsINReady())); | 531 | while (!(Endpoint_IsINReady())) |
| 532 | ; | ||
| 581 | Endpoint_Write_8(keyboard_idle); | 533 | Endpoint_Write_8(keyboard_idle); |
| 582 | Endpoint_ClearIN(); | 534 | Endpoint_ClearIN(); |
| 583 | Endpoint_ClearStatusStage(); | 535 | Endpoint_ClearStatusStage(); |
| @@ -598,54 +550,50 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 598 | * | 550 | * |
| 599 | * FIXME: Needs doc | 551 | * FIXME: Needs doc |
| 600 | */ | 552 | */ |
| 601 | static uint8_t keyboard_leds(void) | 553 | static uint8_t keyboard_leds(void) { return keyboard_led_stats; } |
| 602 | { | ||
| 603 | return keyboard_led_stats; | ||
| 604 | } | ||
| 605 | 554 | ||
| 606 | /** \brief Send Keyboard | 555 | /** \brief Send Keyboard |
| 607 | * | 556 | * |
| 608 | * FIXME: Needs doc | 557 | * FIXME: Needs doc |
| 609 | */ | 558 | */ |
| 610 | static void send_keyboard(report_keyboard_t *report) | 559 | static void send_keyboard(report_keyboard_t *report) { |
| 611 | { | ||
| 612 | uint8_t timeout = 255; | 560 | uint8_t timeout = 255; |
| 613 | uint8_t where = where_to_send(); | 561 | uint8_t where = where_to_send(); |
| 614 | 562 | ||
| 615 | #ifdef BLUETOOTH_ENABLE | 563 | #ifdef BLUETOOTH_ENABLE |
| 616 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { | 564 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { |
| 617 | #ifdef MODULE_ADAFRUIT_BLE | 565 | # ifdef MODULE_ADAFRUIT_BLE |
| 618 | adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys)); | 566 | adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys)); |
| 619 | #elif MODULE_RN42 | 567 | # elif MODULE_RN42 |
| 620 | bluefruit_serial_send(0xFD); | 568 | bluefruit_serial_send(0xFD); |
| 621 | bluefruit_serial_send(0x09); | 569 | bluefruit_serial_send(0x09); |
| 622 | bluefruit_serial_send(0x01); | 570 | bluefruit_serial_send(0x01); |
| 623 | bluefruit_serial_send(report->mods); | 571 | bluefruit_serial_send(report->mods); |
| 624 | bluefruit_serial_send(report->reserved); | 572 | bluefruit_serial_send(report->reserved); |
| 625 | for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | 573 | for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { |
| 626 | bluefruit_serial_send(report->keys[i]); | 574 | bluefruit_serial_send(report->keys[i]); |
| 627 | } | 575 | } |
| 628 | #else | 576 | # else |
| 629 | bluefruit_serial_send(0xFD); | 577 | bluefruit_serial_send(0xFD); |
| 630 | bluefruit_serial_send(report->mods); | 578 | bluefruit_serial_send(report->mods); |
| 631 | bluefruit_serial_send(report->reserved); | 579 | bluefruit_serial_send(report->reserved); |
| 632 | for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | 580 | for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { |
| 633 | bluefruit_serial_send(report->keys[i]); | 581 | bluefruit_serial_send(report->keys[i]); |
| 634 | } | 582 | } |
| 635 | #endif | 583 | # endif |
| 636 | } | 584 | } |
| 637 | #endif | 585 | #endif |
| 638 | 586 | ||
| 639 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { | 587 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { |
| 640 | return; | 588 | return; |
| 641 | } | 589 | } |
| 642 | 590 | ||
| 643 | /* Select the Keyboard Report Endpoint */ | 591 | /* Select the Keyboard Report Endpoint */ |
| 644 | uint8_t ep = KEYBOARD_IN_EPNUM; | 592 | uint8_t ep = KEYBOARD_IN_EPNUM; |
| 645 | uint8_t size = KEYBOARD_REPORT_SIZE; | 593 | uint8_t size = KEYBOARD_REPORT_SIZE; |
| 646 | #ifdef NKRO_ENABLE | 594 | #ifdef NKRO_ENABLE |
| 647 | if (keyboard_protocol && keymap_config.nkro) { | 595 | if (keyboard_protocol && keymap_config.nkro) { |
| 648 | ep = SHARED_IN_EPNUM; | 596 | ep = SHARED_IN_EPNUM; |
| 649 | size = sizeof(struct nkro_report); | 597 | size = sizeof(struct nkro_report); |
| 650 | } | 598 | } |
| 651 | #endif | 599 | #endif |
| @@ -666,38 +614,37 @@ static void send_keyboard(report_keyboard_t *report) | |||
| 666 | 614 | ||
| 667 | keyboard_report_sent = *report; | 615 | keyboard_report_sent = *report; |
| 668 | } | 616 | } |
| 669 | 617 | ||
| 670 | /** \brief Send Mouse | 618 | /** \brief Send Mouse |
| 671 | * | 619 | * |
| 672 | * FIXME: Needs doc | 620 | * FIXME: Needs doc |
| 673 | */ | 621 | */ |
| 674 | static void send_mouse(report_mouse_t *report) | 622 | static void send_mouse(report_mouse_t *report) { |
| 675 | { | ||
| 676 | #ifdef MOUSE_ENABLE | 623 | #ifdef MOUSE_ENABLE |
| 677 | uint8_t timeout = 255; | 624 | uint8_t timeout = 255; |
| 678 | uint8_t where = where_to_send(); | 625 | uint8_t where = where_to_send(); |
| 679 | 626 | ||
| 680 | #ifdef BLUETOOTH_ENABLE | 627 | # ifdef BLUETOOTH_ENABLE |
| 681 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { | 628 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { |
| 682 | #ifdef MODULE_ADAFRUIT_BLE | 629 | # ifdef MODULE_ADAFRUIT_BLE |
| 683 | // FIXME: mouse buttons | 630 | // FIXME: mouse buttons |
| 684 | adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons); | 631 | adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons); |
| 685 | #else | 632 | # else |
| 686 | bluefruit_serial_send(0xFD); | 633 | bluefruit_serial_send(0xFD); |
| 687 | bluefruit_serial_send(0x00); | 634 | bluefruit_serial_send(0x00); |
| 688 | bluefruit_serial_send(0x03); | 635 | bluefruit_serial_send(0x03); |
| 689 | bluefruit_serial_send(report->buttons); | 636 | bluefruit_serial_send(report->buttons); |
| 690 | bluefruit_serial_send(report->x); | 637 | bluefruit_serial_send(report->x); |
| 691 | bluefruit_serial_send(report->y); | 638 | bluefruit_serial_send(report->y); |
| 692 | bluefruit_serial_send(report->v); // should try sending the wheel v here | 639 | bluefruit_serial_send(report->v); // should try sending the wheel v here |
| 693 | bluefruit_serial_send(report->h); // should try sending the wheel h here | 640 | bluefruit_serial_send(report->h); // should try sending the wheel h here |
| 694 | bluefruit_serial_send(0x00); | 641 | bluefruit_serial_send(0x00); |
| 695 | #endif | 642 | # endif |
| 696 | } | 643 | } |
| 697 | #endif | 644 | # endif |
| 698 | 645 | ||
| 699 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { | 646 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { |
| 700 | return; | 647 | return; |
| 701 | } | 648 | } |
| 702 | 649 | ||
| 703 | /* Select the Mouse Report Endpoint */ | 650 | /* Select the Mouse Report Endpoint */ |
| @@ -719,18 +666,13 @@ static void send_mouse(report_mouse_t *report) | |||
| 719 | * | 666 | * |
| 720 | * FIXME: Needs doc | 667 | * FIXME: Needs doc |
| 721 | */ | 668 | */ |
| 722 | static void send_system(uint16_t data) | 669 | static void send_system(uint16_t data) { |
| 723 | { | ||
| 724 | #ifdef EXTRAKEY_ENABLE | 670 | #ifdef EXTRAKEY_ENABLE |
| 725 | uint8_t timeout = 255; | 671 | uint8_t timeout = 255; |
| 726 | 672 | ||
| 727 | if (USB_DeviceState != DEVICE_STATE_Configured) | 673 | if (USB_DeviceState != DEVICE_STATE_Configured) return; |
| 728 | return; | ||
| 729 | 674 | ||
| 730 | report_extra_t r = { | 675 | report_extra_t r = {.report_id = REPORT_ID_SYSTEM, .usage = data - SYSTEM_POWER_DOWN + 1}; |
| 731 | .report_id = REPORT_ID_SYSTEM, | ||
| 732 | .usage = data - SYSTEM_POWER_DOWN + 1 | ||
| 733 | }; | ||
| 734 | Endpoint_SelectEndpoint(SHARED_IN_EPNUM); | 676 | Endpoint_SelectEndpoint(SHARED_IN_EPNUM); |
| 735 | 677 | ||
| 736 | /* Check if write ready for a polling interval around 10ms */ | 678 | /* Check if write ready for a polling interval around 10ms */ |
| @@ -746,52 +688,48 @@ static void send_system(uint16_t data) | |||
| 746 | * | 688 | * |
| 747 | * FIXME: Needs doc | 689 | * FIXME: Needs doc |
| 748 | */ | 690 | */ |
| 749 | static void send_consumer(uint16_t data) | 691 | static void send_consumer(uint16_t data) { |
| 750 | { | ||
| 751 | #ifdef EXTRAKEY_ENABLE | 692 | #ifdef EXTRAKEY_ENABLE |
| 752 | uint8_t timeout = 255; | 693 | uint8_t timeout = 255; |
| 753 | uint8_t where = where_to_send(); | 694 | uint8_t where = where_to_send(); |
| 754 | 695 | ||
| 755 | #ifdef BLUETOOTH_ENABLE | 696 | # ifdef BLUETOOTH_ENABLE |
| 756 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { | 697 | if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { |
| 757 | #ifdef MODULE_ADAFRUIT_BLE | 698 | # ifdef MODULE_ADAFRUIT_BLE |
| 758 | adafruit_ble_send_consumer_key(data, 0); | 699 | adafruit_ble_send_consumer_key(data, 0); |
| 759 | #elif MODULE_RN42 | 700 | # elif MODULE_RN42 |
| 760 | static uint16_t last_data = 0; | 701 | static uint16_t last_data = 0; |
| 761 | if (data == last_data) return; | 702 | if (data == last_data) return; |
| 762 | last_data = data; | 703 | last_data = data; |
| 763 | uint16_t bitmap = CONSUMER2RN42(data); | 704 | uint16_t bitmap = CONSUMER2RN42(data); |
| 764 | bluefruit_serial_send(0xFD); | 705 | bluefruit_serial_send(0xFD); |
| 765 | bluefruit_serial_send(0x03); | 706 | bluefruit_serial_send(0x03); |
| 766 | bluefruit_serial_send(0x03); | 707 | bluefruit_serial_send(0x03); |
| 767 | bluefruit_serial_send(bitmap&0xFF); | 708 | bluefruit_serial_send(bitmap & 0xFF); |
| 768 | bluefruit_serial_send((bitmap>>8)&0xFF); | 709 | bluefruit_serial_send((bitmap >> 8) & 0xFF); |
| 769 | #else | 710 | # else |
| 770 | static uint16_t last_data = 0; | 711 | static uint16_t last_data = 0; |
| 771 | if (data == last_data) return; | 712 | if (data == last_data) return; |
| 772 | last_data = data; | 713 | last_data = data; |
| 773 | uint16_t bitmap = CONSUMER2BLUEFRUIT(data); | 714 | uint16_t bitmap = CONSUMER2BLUEFRUIT(data); |
| 774 | bluefruit_serial_send(0xFD); | 715 | bluefruit_serial_send(0xFD); |
| 775 | bluefruit_serial_send(0x00); | 716 | bluefruit_serial_send(0x00); |
| 776 | bluefruit_serial_send(0x02); | 717 | bluefruit_serial_send(0x02); |
| 777 | bluefruit_serial_send((bitmap>>8)&0xFF); | 718 | bluefruit_serial_send((bitmap >> 8) & 0xFF); |
| 778 | bluefruit_serial_send(bitmap&0xFF); | 719 | bluefruit_serial_send(bitmap & 0xFF); |
| 779 | bluefruit_serial_send(0x00); | 720 | bluefruit_serial_send(0x00); |
| 780 | bluefruit_serial_send(0x00); | 721 | bluefruit_serial_send(0x00); |
| 781 | bluefruit_serial_send(0x00); | 722 | bluefruit_serial_send(0x00); |
| 782 | bluefruit_serial_send(0x00); | 723 | bluefruit_serial_send(0x00); |
| 783 | #endif | 724 | # endif |
| 784 | } | 725 | } |
| 785 | #endif | 726 | # endif |
| 786 | 727 | ||
| 787 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { | 728 | if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { |
| 788 | return; | 729 | return; |
| 789 | } | 730 | } |
| 790 | 731 | ||
| 791 | report_extra_t r = { | 732 | report_extra_t r = {.report_id = REPORT_ID_CONSUMER, .usage = data}; |
| 792 | .report_id = REPORT_ID_CONSUMER, | ||
| 793 | .usage = data | ||
| 794 | }; | ||
| 795 | Endpoint_SelectEndpoint(SHARED_IN_EPNUM); | 733 | Endpoint_SelectEndpoint(SHARED_IN_EPNUM); |
| 796 | 734 | ||
| 797 | /* Check if write ready for a polling interval around 10ms */ | 735 | /* Check if write ready for a polling interval around 10ms */ |
| @@ -803,18 +741,16 @@ static void send_consumer(uint16_t data) | |||
| 803 | #endif | 741 | #endif |
| 804 | } | 742 | } |
| 805 | 743 | ||
| 806 | |||
| 807 | /******************************************************************************* | 744 | /******************************************************************************* |
| 808 | * sendchar | 745 | * sendchar |
| 809 | ******************************************************************************/ | 746 | ******************************************************************************/ |
| 810 | #ifdef CONSOLE_ENABLE | 747 | #ifdef CONSOLE_ENABLE |
| 811 | #define SEND_TIMEOUT 5 | 748 | # define SEND_TIMEOUT 5 |
| 812 | /** \brief Send Char | 749 | /** \brief Send Char |
| 813 | * | 750 | * |
| 814 | * FIXME: Needs doc | 751 | * FIXME: Needs doc |
| 815 | */ | 752 | */ |
| 816 | int8_t sendchar(uint8_t c) | 753 | int8_t sendchar(uint8_t c) { |
| 817 | { | ||
| 818 | // Not wait once timeouted. | 754 | // Not wait once timeouted. |
| 819 | // Because sendchar() is called so many times, waiting each call causes big lag. | 755 | // Because sendchar() is called so many times, waiting each call causes big lag. |
| 820 | static bool timeouted = false; | 756 | static bool timeouted = false; |
| @@ -823,8 +759,7 @@ int8_t sendchar(uint8_t c) | |||
| 823 | // or char will be lost. These two function is mutually exclusive. | 759 | // or char will be lost. These two function is mutually exclusive. |
| 824 | CONSOLE_FLUSH_SET(false); | 760 | CONSOLE_FLUSH_SET(false); |
| 825 | 761 | ||
| 826 | if (USB_DeviceState != DEVICE_STATE_Configured) | 762 | if (USB_DeviceState != DEVICE_STATE_Configured) return -1; |
| 827 | return -1; | ||
| 828 | 763 | ||
| 829 | uint8_t ep = Endpoint_GetCurrentEndpoint(); | 764 | uint8_t ep = Endpoint_GetCurrentEndpoint(); |
| 830 | Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); | 765 | Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM); |
| @@ -857,7 +792,8 @@ int8_t sendchar(uint8_t c) | |||
| 857 | 792 | ||
| 858 | // send when bank is full | 793 | // send when bank is full |
| 859 | if (!Endpoint_IsReadWriteAllowed()) { | 794 | if (!Endpoint_IsReadWriteAllowed()) { |
| 860 | while (!(Endpoint_IsINReady())); | 795 | while (!(Endpoint_IsINReady())) |
| 796 | ; | ||
| 861 | Endpoint_ClearIN(); | 797 | Endpoint_ClearIN(); |
| 862 | } else { | 798 | } else { |
| 863 | CONSOLE_FLUSH_SET(true); | 799 | CONSOLE_FLUSH_SET(true); |
| @@ -870,10 +806,7 @@ ERROR_EXIT: | |||
| 870 | return -1; | 806 | return -1; |
| 871 | } | 807 | } |
| 872 | #else | 808 | #else |
| 873 | int8_t sendchar(uint8_t c) | 809 | int8_t sendchar(uint8_t c) { return 0; } |
| 874 | { | ||
| 875 | return 0; | ||
| 876 | } | ||
| 877 | #endif | 810 | #endif |
| 878 | 811 | ||
| 879 | /******************************************************************************* | 812 | /******************************************************************************* |
| @@ -881,33 +814,28 @@ int8_t sendchar(uint8_t c) | |||
| 881 | ******************************************************************************/ | 814 | ******************************************************************************/ |
| 882 | 815 | ||
| 883 | #ifdef MIDI_ENABLE | 816 | #ifdef MIDI_ENABLE |
| 884 | USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = | 817 | USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = { |
| 885 | { | 818 | .Config = |
| 886 | .Config = | 819 | { |
| 887 | { | 820 | .StreamingInterfaceNumber = AS_INTERFACE, |
| 888 | .StreamingInterfaceNumber = AS_INTERFACE, | 821 | .DataINEndpoint = |
| 889 | .DataINEndpoint = | 822 | { |
| 890 | { | 823 | .Address = MIDI_STREAM_IN_EPADDR, |
| 891 | .Address = MIDI_STREAM_IN_EPADDR, | 824 | .Size = MIDI_STREAM_EPSIZE, |
| 892 | .Size = MIDI_STREAM_EPSIZE, | 825 | .Banks = 1, |
| 893 | .Banks = 1, | 826 | }, |
| 894 | }, | 827 | .DataOUTEndpoint = |
| 895 | .DataOUTEndpoint = | 828 | { |
| 896 | { | 829 | .Address = MIDI_STREAM_OUT_EPADDR, |
| 897 | .Address = MIDI_STREAM_OUT_EPADDR, | 830 | .Size = MIDI_STREAM_EPSIZE, |
| 898 | .Size = MIDI_STREAM_EPSIZE, | 831 | .Banks = 1, |
| 899 | .Banks = 1, | 832 | }, |
| 900 | }, | 833 | }, |
| 901 | }, | ||
| 902 | }; | 834 | }; |
| 903 | 835 | ||
| 904 | void send_midi_packet(MIDI_EventPacket_t* event) { | 836 | void send_midi_packet(MIDI_EventPacket_t *event) { MIDI_Device_SendEventPacket(&USB_MIDI_Interface, event); } |
| 905 | MIDI_Device_SendEventPacket(&USB_MIDI_Interface, event); | ||
| 906 | } | ||
| 907 | 837 | ||
| 908 | bool recv_midi_packet(MIDI_EventPacket_t* const event) { | 838 | bool recv_midi_packet(MIDI_EventPacket_t *const event) { return MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, event); } |
| 909 | return MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, event); | ||
| 910 | } | ||
| 911 | 839 | ||
| 912 | #endif | 840 | #endif |
| 913 | 841 | ||
| @@ -920,66 +848,60 @@ bool recv_midi_packet(MIDI_EventPacket_t* const event) { | |||
| 920 | * | 848 | * |
| 921 | * FIXME: Needs doc | 849 | * FIXME: Needs doc |
| 922 | */ | 850 | */ |
| 923 | void virtser_init(void) | 851 | void virtser_init(void) { |
| 924 | { | 852 | cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR; |
| 925 | cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ; | 853 | CDC_Device_SendControlLineStateChange(&cdc_device); |
| 926 | CDC_Device_SendControlLineStateChange(&cdc_device); | ||
| 927 | } | 854 | } |
| 928 | 855 | ||
| 929 | /** \brief Virtual Serial Receive | 856 | /** \brief Virtual Serial Receive |
| 930 | * | 857 | * |
| 931 | * FIXME: Needs doc | 858 | * FIXME: Needs doc |
| 932 | */ | 859 | */ |
| 933 | void virtser_recv(uint8_t c) __attribute__ ((weak)); | 860 | void virtser_recv(uint8_t c) __attribute__((weak)); |
| 934 | void virtser_recv(uint8_t c) | 861 | void virtser_recv(uint8_t c) { |
| 935 | { | 862 | // Ignore by default |
| 936 | // Ignore by default | ||
| 937 | } | 863 | } |
| 938 | 864 | ||
| 939 | /** \brief Virtual Serial Task | 865 | /** \brief Virtual Serial Task |
| 940 | * | 866 | * |
| 941 | * FIXME: Needs doc | 867 | * FIXME: Needs doc |
| 942 | */ | 868 | */ |
| 943 | void virtser_task(void) | 869 | void virtser_task(void) { |
| 944 | { | 870 | uint16_t count = CDC_Device_BytesReceived(&cdc_device); |
| 945 | uint16_t count = CDC_Device_BytesReceived(&cdc_device); | 871 | uint8_t ch; |
| 946 | uint8_t ch; | 872 | if (count) { |
| 947 | if (count) | 873 | ch = CDC_Device_ReceiveByte(&cdc_device); |
| 948 | { | 874 | virtser_recv(ch); |
| 949 | ch = CDC_Device_ReceiveByte(&cdc_device); | 875 | } |
| 950 | virtser_recv(ch); | ||
| 951 | } | ||
| 952 | } | 876 | } |
| 953 | /** \brief Virtual Serial Send | 877 | /** \brief Virtual Serial Send |
| 954 | * | 878 | * |
| 955 | * FIXME: Needs doc | 879 | * FIXME: Needs doc |
| 956 | */ | 880 | */ |
| 957 | void virtser_send(const uint8_t byte) | 881 | void virtser_send(const uint8_t byte) { |
| 958 | { | 882 | uint8_t timeout = 255; |
| 959 | uint8_t timeout = 255; | 883 | uint8_t ep = Endpoint_GetCurrentEndpoint(); |
| 960 | uint8_t ep = Endpoint_GetCurrentEndpoint(); | ||
| 961 | 884 | ||
| 962 | if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) | 885 | if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) { |
| 963 | { | 886 | /* IN packet */ |
| 964 | /* IN packet */ | 887 | Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address); |
| 965 | Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address); | ||
| 966 | 888 | ||
| 967 | if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) { | 889 | if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) { |
| 968 | Endpoint_SelectEndpoint(ep); | 890 | Endpoint_SelectEndpoint(ep); |
| 969 | return; | 891 | return; |
| 970 | } | 892 | } |
| 971 | 893 | ||
| 972 | while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | 894 | while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); |
| 973 | 895 | ||
| 974 | Endpoint_Write_8(byte); | 896 | Endpoint_Write_8(byte); |
| 975 | CDC_Device_Flush(&cdc_device); | 897 | CDC_Device_Flush(&cdc_device); |
| 976 | 898 | ||
| 977 | if (Endpoint_IsINReady()) { | 899 | if (Endpoint_IsINReady()) { |
| 978 | Endpoint_ClearIN(); | 900 | Endpoint_ClearIN(); |
| 979 | } | 901 | } |
| 980 | 902 | ||
| 981 | Endpoint_SelectEndpoint(ep); | 903 | Endpoint_SelectEndpoint(ep); |
| 982 | } | 904 | } |
| 983 | } | 905 | } |
| 984 | #endif | 906 | #endif |
| 985 | 907 | ||
| @@ -990,8 +912,7 @@ void virtser_send(const uint8_t byte) | |||
| 990 | * | 912 | * |
| 991 | * FIXME: Needs doc | 913 | * FIXME: Needs doc |
| 992 | */ | 914 | */ |
| 993 | static void setup_mcu(void) | 915 | static void setup_mcu(void) { |
| 994 | { | ||
| 995 | /* Disable watchdog if enabled by bootloader/fuses */ | 916 | /* Disable watchdog if enabled by bootloader/fuses */ |
| 996 | MCUSR &= ~(1 << WDRF); | 917 | MCUSR &= ~(1 << WDRF); |
| 997 | wdt_disable(); | 918 | wdt_disable(); |
| @@ -1007,8 +928,7 @@ static void setup_mcu(void) | |||
| 1007 | * | 928 | * |
| 1008 | * FIXME: Needs doc | 929 | * FIXME: Needs doc |
| 1009 | */ | 930 | */ |
| 1010 | static void setup_usb(void) | 931 | static void setup_usb(void) { |
| 1011 | { | ||
| 1012 | // Leonardo needs. Without this USB device is not recognized. | 932 | // Leonardo needs. Without this USB device is not recognized. |
| 1013 | USB_Disable(); | 933 | USB_Disable(); |
| 1014 | 934 | ||
| @@ -1023,9 +943,8 @@ static void setup_usb(void) | |||
| 1023 | * | 943 | * |
| 1024 | * FIXME: Needs doc | 944 | * FIXME: Needs doc |
| 1025 | */ | 945 | */ |
| 1026 | int main(void) __attribute__ ((weak)); | 946 | int main(void) __attribute__((weak)); |
| 1027 | int main(void) | 947 | int main(void) { |
| 1028 | { | ||
| 1029 | #ifdef MIDI_ENABLE | 948 | #ifdef MIDI_ENABLE |
| 1030 | setup_midi(); | 949 | setup_midi(); |
| 1031 | #endif | 950 | #endif |
| @@ -1043,11 +962,11 @@ int main(void) | |||
| 1043 | 962 | ||
| 1044 | #ifdef WAIT_FOR_USB | 963 | #ifdef WAIT_FOR_USB |
| 1045 | while (USB_DeviceState != DEVICE_STATE_Configured) { | 964 | while (USB_DeviceState != DEVICE_STATE_Configured) { |
| 1046 | #if defined(INTERRUPT_CONTROL_ENDPOINT) | 965 | # if defined(INTERRUPT_CONTROL_ENDPOINT) |
| 1047 | ; | 966 | ; |
| 1048 | #else | 967 | # else |
| 1049 | USB_USBTask(); | 968 | USB_USBTask(); |
| 1050 | #endif | 969 | # endif |
| 1051 | } | 970 | } |
| 1052 | print("USB configured.\n"); | 971 | print("USB configured.\n"); |
| 1053 | #else | 972 | #else |
| @@ -1066,15 +985,15 @@ int main(void) | |||
| 1066 | 985 | ||
| 1067 | print("Keyboard start.\n"); | 986 | print("Keyboard start.\n"); |
| 1068 | while (1) { | 987 | while (1) { |
| 1069 | #if !defined(NO_USB_STARTUP_CHECK) | 988 | #if !defined(NO_USB_STARTUP_CHECK) |
| 1070 | while (USB_DeviceState == DEVICE_STATE_Suspended) { | 989 | while (USB_DeviceState == DEVICE_STATE_Suspended) { |
| 1071 | print("[s]"); | 990 | print("[s]"); |
| 1072 | suspend_power_down(); | 991 | suspend_power_down(); |
| 1073 | if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { | 992 | if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { |
| 1074 | USB_Device_SendRemoteWakeup(); | 993 | USB_Device_SendRemoteWakeup(); |
| 1075 | } | 994 | } |
| 1076 | } | 995 | } |
| 1077 | #endif | 996 | #endif |
| 1078 | 997 | ||
| 1079 | keyboard_task(); | 998 | keyboard_task(); |
| 1080 | 999 | ||
| @@ -1102,14 +1021,7 @@ int main(void) | |||
| 1102 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | 1021 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) |
| 1103 | USB_USBTask(); | 1022 | USB_USBTask(); |
| 1104 | #endif | 1023 | #endif |
| 1105 | |||
| 1106 | } | 1024 | } |
| 1107 | } | 1025 | } |
| 1108 | 1026 | ||
| 1109 | uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, | 1027 | uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint16_t wIndex, const void **const DescriptorAddress) { return get_usb_descriptor(wValue, wIndex, DescriptorAddress); } |
| 1110 | const uint16_t wIndex, | ||
| 1111 | const void** const DescriptorAddress) | ||
| 1112 | { | ||
| 1113 | return get_usb_descriptor(wValue, wIndex, DescriptorAddress); | ||
| 1114 | } | ||
| 1115 | |||
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h index 7364cdf7c..652e4e79b 100644 --- a/tmk_core/protocol/lufa/lufa.h +++ b/tmk_core/protocol/lufa/lufa.h | |||
| @@ -62,27 +62,27 @@ extern host_driver_t lufa_driver; | |||
| 62 | typedef struct { | 62 | typedef struct { |
| 63 | uint8_t report_id; | 63 | uint8_t report_id; |
| 64 | uint16_t usage; | 64 | uint16_t usage; |
| 65 | } __attribute__ ((packed)) report_extra_t; | 65 | } __attribute__((packed)) report_extra_t; |
| 66 | 66 | ||
| 67 | #ifdef API_ENABLE | 67 | #ifdef API_ENABLE |
| 68 | #include "api.h" | 68 | # include "api.h" |
| 69 | #endif | 69 | #endif |
| 70 | 70 | ||
| 71 | #ifdef API_SYSEX_ENABLE | 71 | #ifdef API_SYSEX_ENABLE |
| 72 | #include "api_sysex.h" | 72 | # include "api_sysex.h" |
| 73 | // Allocate space for encoding overhead. | 73 | // Allocate space for encoding overhead. |
| 74 | //The header and terminator are not stored to save a few bytes of precious ram | 74 | // The header and terminator are not stored to save a few bytes of precious ram |
| 75 | #define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0)) | 75 | # define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0)) |
| 76 | #endif | 76 | #endif |
| 77 | 77 | ||
| 78 | // #if LUFA_VERSION_INTEGER < 0x120730 | 78 | // #if LUFA_VERSION_INTEGER < 0x120730 |
| 79 | // /* old API 120219 */ | 79 | // /* old API 120219 */ |
| 80 | // #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank) | 80 | // #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank) |
| 81 | // #else | 81 | // #else |
| 82 | /* new API >= 120730 */ | 82 | /* new API >= 120730 */ |
| 83 | #define ENDPOINT_BANK_SINGLE 1 | 83 | #define ENDPOINT_BANK_SINGLE 1 |
| 84 | #define ENDPOINT_BANK_DOUBLE 2 | 84 | #define ENDPOINT_BANK_DOUBLE 2 |
| 85 | #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank) | 85 | #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum), eptype, epsize, epbank) |
| 86 | // #endif | 86 | // #endif |
| 87 | 87 | ||
| 88 | #endif | 88 | #endif |
diff --git a/tmk_core/protocol/lufa/outputselect.c b/tmk_core/protocol/lufa/outputselect.c index 42de80612..b115ea969 100644 --- a/tmk_core/protocol/lufa/outputselect.c +++ b/tmk_core/protocol/lufa/outputselect.c | |||
| @@ -15,7 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 15 | #include "lufa.h" | 15 | #include "lufa.h" |
| 16 | #include "outputselect.h" | 16 | #include "outputselect.h" |
| 17 | #ifdef MODULE_ADAFRUIT_BLE | 17 | #ifdef MODULE_ADAFRUIT_BLE |
| 18 | #include "adafruit_ble.h" | 18 | # include "adafruit_ble.h" |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | uint8_t desired_output = OUTPUT_DEFAULT; | 21 | uint8_t desired_output = OUTPUT_DEFAULT; |
| @@ -33,9 +33,7 @@ void set_output(uint8_t output) { | |||
| 33 | * | 33 | * |
| 34 | * FIXME: Needs doc | 34 | * FIXME: Needs doc |
| 35 | */ | 35 | */ |
| 36 | __attribute__((weak)) | 36 | __attribute__((weak)) void set_output_user(uint8_t output) {} |
| 37 | void set_output_user(uint8_t output) { | ||
| 38 | } | ||
| 39 | 37 | ||
| 40 | /** \brief Auto Detect Output | 38 | /** \brief Auto Detect Output |
| 41 | * | 39 | * |
| @@ -53,7 +51,7 @@ uint8_t auto_detect_output(void) { | |||
| 53 | #endif | 51 | #endif |
| 54 | 52 | ||
| 55 | #ifdef BLUETOOTH_ENABLE | 53 | #ifdef BLUETOOTH_ENABLE |
| 56 | return OUTPUT_BLUETOOTH; // should check if BT is connected here | 54 | return OUTPUT_BLUETOOTH; // should check if BT is connected here |
| 57 | #endif | 55 | #endif |
| 58 | 56 | ||
| 59 | return OUTPUT_NONE; | 57 | return OUTPUT_NONE; |
| @@ -69,4 +67,3 @@ uint8_t where_to_send(void) { | |||
| 69 | } | 67 | } |
| 70 | return desired_output; | 68 | return desired_output; |
| 71 | } | 69 | } |
| 72 | |||
diff --git a/tmk_core/protocol/lufa/outputselect.h b/tmk_core/protocol/lufa/outputselect.h index 28cc3298e..24fe4daa2 100644 --- a/tmk_core/protocol/lufa/outputselect.h +++ b/tmk_core/protocol/lufa/outputselect.h | |||
| @@ -27,14 +27,14 @@ enum outputs { | |||
| 27 | * backward compatibility for BLUETOOTH_ENABLE, send to BT and USB by default | 27 | * backward compatibility for BLUETOOTH_ENABLE, send to BT and USB by default |
| 28 | */ | 28 | */ |
| 29 | #ifndef OUTPUT_DEFAULT | 29 | #ifndef OUTPUT_DEFAULT |
| 30 | #ifdef BLUETOOTH_ENABLE | 30 | # ifdef BLUETOOTH_ENABLE |
| 31 | #define OUTPUT_DEFAULT OUTPUT_USB_AND_BT | 31 | # define OUTPUT_DEFAULT OUTPUT_USB_AND_BT |
| 32 | #else | 32 | # else |
| 33 | #define OUTPUT_DEFAULT OUTPUT_AUTO | 33 | # define OUTPUT_DEFAULT OUTPUT_AUTO |
| 34 | #endif | 34 | # endif |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | void set_output(uint8_t output); | 37 | void set_output(uint8_t output); |
| 38 | void set_output_user(uint8_t output); | 38 | void set_output_user(uint8_t output); |
| 39 | uint8_t auto_detect_output(void); | 39 | uint8_t auto_detect_output(void); |
| 40 | uint8_t where_to_send(void); \ No newline at end of file | 40 | uint8_t where_to_send(void); \ No newline at end of file |
