@@ -51,8 +51,8 @@ | |||
#include "usb_serial.h" | |||
#include "usb_seremu.h" | |||
#include "usb_keyboard.h" | |||
//#include "usb_mouse.h" | |||
//#include "usb_joystick.h" | |||
#include "usb_mouse.h" | |||
#include "usb_joystick.h" | |||
//#include "usb_midi.h" | |||
#include "usb_rawhid.h" | |||
//#include "usb_flightsim.h" |
@@ -4,6 +4,8 @@ | |||
#include "usb_serial.h" | |||
#include "usb_seremu.h" | |||
#include "usb_keyboard.h" | |||
#include "usb_mouse.h" | |||
#include "usb_joystick.h" | |||
#include "core_pins.h" // for delay() | |||
#include "avr/pgmspace.h" | |||
#include <string.h> | |||
@@ -370,6 +372,12 @@ static void endpoint0_setup(uint64_t setupdata) | |||
#if defined(KEYBOARD_INTERFACE) | |||
usb_keyboard_configure(); | |||
#endif | |||
#if defined(MOUSE_INTERFACE) | |||
usb_mouse_configure(); | |||
#endif | |||
#if defined(JOYSTICK_INTERFACE) | |||
usb_joystick_configure(); | |||
#endif | |||
endpoint0_receive(NULL, 0, 0); | |||
return; | |||
case 0x0880: // GET_CONFIGURATION |
@@ -78,12 +78,6 @@ interfaces, usually these other settings should not be changed. | |||
Edit NUM_ENDPOINTS to be at least the largest endpoint number used. | |||
Edit NUM_USB_BUFFERS to control how much memory the USB stack will | |||
allocate. At least 2 should be used for each endpoint. More | |||
memory will allow higher throughput for user programs that have | |||
high latency (eg, spending time doing things other than interacting | |||
with the USB). | |||
Edit the ENDPOINT*_CONFIG lines so each endpoint is configured | |||
the proper way (transmit, receive, or both). | |||
@@ -185,7 +179,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define NUM_USB_BUFFERS 24 | |||
#define NUM_INTERFACE 5 | |||
#define SEREMU_INTERFACE 2 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
#define SEREMU_TX_ENDPOINT 2 | |||
#define SEREMU_TX_SIZE 64 | |||
#define SEREMU_TX_INTERVAL 1 | |||
#define SEREMU_RX_ENDPOINT 2 | |||
@@ -196,7 +190,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define KEYBOARD_SIZE 8 | |||
#define KEYBOARD_INTERVAL 1 | |||
#define KEYMEDIA_INTERFACE 4 // Keyboard Media Keys | |||
#define KEYMEDIA_ENDPOINT 6 | |||
#define KEYMEDIA_ENDPOINT 4 | |||
#define KEYMEDIA_SIZE 8 | |||
#define KEYMEDIA_INTERVAL 4 | |||
#define MOUSE_INTERFACE 1 // Mouse | |||
@@ -204,15 +198,14 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define MOUSE_SIZE 8 | |||
#define MOUSE_INTERVAL 1 | |||
#define JOYSTICK_INTERFACE 3 // Joystick | |||
#define JOYSTICK_ENDPOINT 4 | |||
#define JOYSTICK_ENDPOINT 6 | |||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||
#define JOYSTICK_INTERVAL 2 | |||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY | |||
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_INTERRUPT + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#elif defined(USB_SERIAL_HID) | |||
#define VENDOR_ID 0x16C0 | |||
@@ -226,40 +219,40 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 30 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 7 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 6 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
#define CDC_DATA_INTERFACE 1 // Serial | |||
#define CDC_ACM_ENDPOINT 2 | |||
#define CDC_RX_ENDPOINT 3 | |||
#define CDC_TX_ENDPOINT 4 | |||
#define CDC_TX_ENDPOINT 3 | |||
#define CDC_ACM_SIZE 16 | |||
#define CDC_RX_SIZE 64 | |||
#define CDC_TX_SIZE 64 | |||
#define CDC_RX_SIZE_480 512 | |||
#define CDC_TX_SIZE_480 512 | |||
#define CDC_RX_SIZE_12 64 | |||
#define CDC_TX_SIZE_12 64 | |||
#define KEYBOARD_INTERFACE 2 // Keyboard | |||
#define KEYBOARD_ENDPOINT 1 | |||
#define KEYBOARD_ENDPOINT 4 | |||
#define KEYBOARD_SIZE 8 | |||
#define KEYBOARD_INTERVAL 1 | |||
#define KEYMEDIA_INTERFACE 5 // Keyboard Media Keys | |||
#define KEYMEDIA_ENDPOINT 7 | |||
#define KEYMEDIA_ENDPOINT 5 | |||
#define KEYMEDIA_SIZE 8 | |||
#define KEYMEDIA_INTERVAL 4 | |||
#define MOUSE_INTERFACE 3 // Mouse | |||
#define MOUSE_ENDPOINT 5 | |||
#define MOUSE_ENDPOINT 6 | |||
#define MOUSE_SIZE 8 | |||
#define MOUSE_INTERVAL 2 | |||
#define JOYSTICK_INTERFACE 4 // Joystick | |||
#define JOYSTICK_ENDPOINT 6 | |||
#define JOYSTICK_ENDPOINT 7 | |||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||
#define JOYSTICK_INTERVAL 1 | |||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY | |||
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_BULK + ENDPOINT_TRANSMIT_BULK | |||
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_INTERRUPT | |||
#elif defined(USB_TOUCHSCREEN) | |||
#define VENDOR_ID 0x16C0 | |||
@@ -270,7 +263,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 20 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 15 | |||
#define NUM_INTERFACE 4 | |||
#define SEREMU_INTERFACE 1 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -306,7 +298,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 26 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 6 | |||
#define NUM_USB_BUFFERS 20 | |||
#define NUM_INTERFACE 5 | |||
#define SEREMU_INTERFACE 2 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -347,7 +338,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 11 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 16 | |||
#define NUM_INTERFACE 2 | |||
#define SEREMU_INTERFACE 1 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -377,7 +367,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 13 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 16 | |||
#define NUM_INTERFACE 2 | |||
#define SEREMU_INTERFACE 1 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -407,7 +396,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 14 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 16 | |||
#define NUM_INTERFACE 2 | |||
#define SEREMU_INTERFACE 1 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -436,7 +424,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 11 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 3 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
@@ -469,7 +456,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 13 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 3 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
@@ -502,7 +488,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 14 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 3 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
@@ -536,7 +521,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 18 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 12 | |||
#define NUM_INTERFACE 2 | |||
#define RAWHID_INTERFACE 0 // RawHID | |||
#define RAWHID_TX_ENDPOINT 3 | |||
@@ -565,7 +549,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 26 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 20 | |||
#define NUM_INTERFACE 2 | |||
#define FLIGHTSIM_INTERFACE 0 // Flight Sim Control | |||
#define FLIGHTSIM_TX_ENDPOINT 3 | |||
@@ -596,7 +579,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 26 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 20 | |||
#define NUM_INTERFACE 3 | |||
#define FLIGHTSIM_INTERFACE 0 // Flight Sim Control | |||
#define FLIGHTSIM_TX_ENDPOINT 3 | |||
@@ -632,7 +614,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 15 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 4 | |||
#define NUM_USB_BUFFERS 20 | |||
#define NUM_INTERFACE 2 | |||
#define MTP_INTERFACE 0 // MTP Disk | |||
#define MTP_TX_ENDPOINT 3 | |||
@@ -663,7 +644,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 12 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_USB_BUFFERS 16 | |||
#define NUM_INTERFACE 4 | |||
#define SEREMU_INTERFACE 0 // Serial emulation | |||
#define SEREMU_TX_ENDPOINT 1 | |||
@@ -693,7 +673,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 17 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 8 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 6 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
@@ -735,7 +714,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 20 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 8 | |||
#define NUM_USB_BUFFERS 30 | |||
#define NUM_INTERFACE 6 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 | |||
@@ -781,7 +759,6 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
#define PRODUCT_NAME_LEN 14 | |||
#define EP0_SIZE 64 | |||
#define NUM_ENDPOINTS 15 | |||
#define NUM_USB_BUFFERS 31 | |||
#define NUM_INTERFACE 13 | |||
#define CDC_IAD_DESCRIPTOR 1 | |||
#define CDC_STATUS_INTERFACE 0 |
@@ -0,0 +1,109 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2017 PJRC.COM, LLC. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sublicense, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* 1. The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* 2. If the Software is incorporated into a build system that allows | |||
* selection among a list of target devices, then similar target | |||
* devices manufactured by PJRC.COM must be included in the list of | |||
* target devices and selectable in the same manner. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#include "usb_dev.h" | |||
#include "usb_joystick.h" | |||
#include "core_pins.h" // for yield() | |||
#include <string.h> // for memcpy() | |||
#include "avr/pgmspace.h" // for PROGMEM, DMAMEM, FASTRUN | |||
#include "debug/printf.h" | |||
#include "core_pins.h" | |||
#ifdef JOYSTICK_INTERFACE // defined by usb_dev.h -> usb_desc.h | |||
uint32_t usb_joystick_data[(JOYSTICK_SIZE+3)/4]; | |||
static uint8_t transmit_previous_timeout=0; | |||
// When the PC isn't listening, how long do we wait before discarding data? | |||
#define TX_TIMEOUT_MSEC 30 | |||
#define TX_NUM 4 | |||
#if JOYSTICK_SIZE <= 32 | |||
#define TX_BUFSIZE 32 | |||
#else | |||
#define TX_BUFSIZE 64 | |||
#endif | |||
static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32))); | |||
DMAMEM static uint8_t txbuffer[TX_NUM * TX_BUFSIZE] __attribute__ ((aligned(32))); | |||
static uint8_t tx_head=0; | |||
#if JOYSTICK_SIZE > TX_BUFSIZE | |||
#error "Internal error, transmit buffer size is too small for joystick endpoint" | |||
#endif | |||
void usb_joystick_configure(void) | |||
{ | |||
memset(tx_transfer, 0, sizeof(tx_transfer)); | |||
tx_head = 0; | |||
usb_config_tx(JOYSTICK_ENDPOINT, JOYSTICK_SIZE, 0, NULL); | |||
} | |||
int usb_joystick_send() | |||
{ | |||
if (!usb_configuration) return -1; | |||
uint32_t head = tx_head; | |||
transfer_t *xfer = tx_transfer + head; | |||
uint32_t wait_begin_at = systick_millis_count; | |||
while (1) { | |||
uint32_t status = usb_transfer_status(xfer); | |||
if (!(status & 0x80)) { | |||
if (status & 0x68) { | |||
// TODO: what if status has errors??? | |||
printf("ERROR status = %x, i=%d, ms=%u\n", | |||
status, tx_head, systick_millis_count); | |||
} | |||
transmit_previous_timeout = 0; | |||
break; | |||
} | |||
if (transmit_previous_timeout) return -1; | |||
if (systick_millis_count - wait_begin_at > TX_TIMEOUT_MSEC) { | |||
// waited too long, assume the USB host isn't listening | |||
transmit_previous_timeout = 1; | |||
return -1; | |||
} | |||
if (!usb_configuration) return -1; | |||
yield(); | |||
} | |||
uint8_t *buffer = txbuffer + head * TX_BUFSIZE; | |||
memcpy(buffer, usb_joystick_data, JOYSTICK_SIZE); | |||
usb_prepare_transfer(xfer, buffer, JOYSTICK_SIZE, 0); | |||
arm_dcache_flush_delete(buffer, TX_BUFSIZE); | |||
usb_transmit(JOYSTICK_ENDPOINT, xfer); | |||
if (++head >= TX_NUM) head = 0; | |||
tx_head = head; | |||
return 0; | |||
} | |||
#endif // JOYSTICK_INTERFACE |
@@ -0,0 +1,194 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2017 PJRC.COM, LLC. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sublicense, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* 1. The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* 2. If the Software is incorporated into a build system that allows | |||
* selection among a list of target devices, then similar target | |||
* devices manufactured by PJRC.COM must be included in the list of | |||
* target devices and selectable in the same manner. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#ifndef USBjoystick_h_ | |||
#define USBjoystick_h_ | |||
#include "usb_desc.h" | |||
#if defined(JOYSTICK_INTERFACE) | |||
#include <inttypes.h> | |||
// C language implementation | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
void usb_joystick_configure(void); | |||
int usb_joystick_send(void); | |||
extern uint32_t usb_joystick_data[(JOYSTICK_SIZE+3)/4]; | |||
extern volatile uint8_t usb_configuration; | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
// C++ interface | |||
#ifdef __cplusplus | |||
class usb_joystick_class | |||
{ | |||
public: | |||
void begin(void) { } | |||
void end(void) { } | |||
#if JOYSTICK_SIZE == 12 | |||
void button(uint8_t button, bool val) { | |||
if (--button >= 32) return; | |||
if (val) usb_joystick_data[0] |= (1 << button); | |||
else usb_joystick_data[0] &= ~(1 << button); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void X(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFC00F) | (val << 4); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void Y(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[1] = (usb_joystick_data[1] & 0xFF003FFF) | (val << 14); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void position(unsigned int x, unsigned int y) { | |||
if (x > 1023) x = 1023; | |||
if (y > 1023) y = 1023; | |||
usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFF00000) | |||
| (x << 4) | (y << 14); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void Z(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[1] = (usb_joystick_data[1] & 0x00FFFFFF) | (val << 24); | |||
usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFFFFFFC) | (val >> 8); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void Zrotate(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFFFF003) | (val << 2); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void sliderLeft(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFC00FFF) | (val << 12); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void sliderRight(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[2] = (usb_joystick_data[2] & 0x003FFFFF) | (val << 22); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void slider(unsigned int val) { | |||
if (val > 1023) val = 1023; | |||
usb_joystick_data[2] = (usb_joystick_data[2] & 0x00000FFF) | |||
| (val << 12) | (val << 22); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
inline void hat(int dir) { | |||
uint32_t val = 0; | |||
if (dir < 0) val = 15; | |||
else if (dir < 23) val = 0; | |||
else if (dir < 68) val = 1; | |||
else if (dir < 113) val = 2; | |||
else if (dir < 158) val = 3; | |||
else if (dir < 203) val = 4; | |||
else if (dir < 245) val = 5; | |||
else if (dir < 293) val = 6; | |||
else if (dir < 338) val = 7; | |||
usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFFFF0) | val; | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
#elif JOYSTICK_SIZE == 64 | |||
void button(unsigned int num, bool val) { | |||
if (--num >= 128) return; | |||
uint32_t *p = usb_joystick_data + (num >> 5); | |||
num &= 0x1F; | |||
if (val) *p |= (1 << num); | |||
else *p &= ~(1 << num); | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
void X(unsigned int position) { analog16(0, position); } | |||
void Y(unsigned int position) { analog16(1, position); } | |||
void Z(unsigned int position) { analog16(2, position); } | |||
void Xrotate(unsigned int position) { analog16(3, position); } | |||
void Yrotate(unsigned int position) { analog16(4, position); } | |||
void Zrotate(unsigned int position) { analog16(5, position); } | |||
void slider(unsigned int num, unsigned int position) { | |||
if (--num >= 17) return; | |||
analog16(num + 6, position); | |||
} | |||
inline void hat(unsigned int num, int angle) { | |||
uint32_t val=15; | |||
if (angle > 0 && angle < 23) val = 0; | |||
else if (angle < 68) val = 1; | |||
else if (angle < 113) val = 2; | |||
else if (angle < 158) val = 3; | |||
else if (angle < 203) val = 4; | |||
else if (angle < 245) val = 5; | |||
else if (angle < 293) val = 6; | |||
else if (angle < 338) val = 7; | |||
else if (angle < 360) val = 0; | |||
uint32_t *p = usb_joystick_data; | |||
switch(num) { | |||
case 1: | |||
p[15] = (p[15] & 0xFFF0FFFF) | (val << 16); break; | |||
case 2: | |||
p[15] = (p[15] & 0xFF0FFFFF) | (val << 20); break; | |||
case 3: | |||
p[15] = (p[15] & 0xF0FFFFFF) | (val << 24); break; | |||
case 4: | |||
p[15] = (p[15] & 0x0FFFFFFF) | (val << 28); break; | |||
default: | |||
return; | |||
} | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
#endif | |||
void useManualSend(bool mode) { | |||
manual_mode = mode; | |||
} | |||
void send_now(void) { | |||
usb_joystick_send(); | |||
} | |||
private: | |||
static uint8_t manual_mode; | |||
#if JOYSTICK_SIZE == 64 | |||
void analog16(unsigned int num, unsigned int value) { | |||
if (value > 0xFFFF) value = 0xFFFF; | |||
uint16_t *p = (uint16_t *)(&usb_joystick_data[4]); | |||
p[num] = value; | |||
if (!manual_mode) usb_joystick_send(); | |||
} | |||
#endif | |||
}; | |||
extern usb_joystick_class Joystick; | |||
#endif // __cplusplus | |||
#endif // JOYSTICK_INTERFACE | |||
#endif // USBjoystick_h_ | |||
@@ -518,7 +518,7 @@ static uint8_t transmit_previous_timeout=0; | |||
// When the PC isn't listening, how long do we wait before discarding data? | |||
#define TX_TIMEOUT_MSEC 50 | |||
int usb_keyboard_transmit(int endpoint, const uint8_t *data, uint32_t len) | |||
static int usb_keyboard_transmit(int endpoint, const uint8_t *data, uint32_t len) | |||
{ | |||
if (!usb_configuration) return -1; | |||
uint32_t head = tx_head; |
@@ -0,0 +1,236 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2019 PJRC.COM, LLC. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sublicense, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* 1. The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* 2. If the Software is incorporated into a build system that allows | |||
* selection among a list of target devices, then similar target | |||
* devices manufactured by PJRC.COM must be included in the list of | |||
* target devices and selectable in the same manner. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#include "usb_dev.h" | |||
#include "usb_mouse.h" | |||
#include "core_pins.h" // for yield() | |||
#include <string.h> // for memcpy() | |||
#include "avr/pgmspace.h" // for PROGMEM, DMAMEM, FASTRUN | |||
#include "debug/printf.h" | |||
#include "core_pins.h" | |||
#ifdef MOUSE_INTERFACE // defined by usb_dev.h -> usb_desc.h | |||
// which buttons are currently pressed | |||
uint8_t usb_mouse_buttons_state=0; | |||
//#define DEFAULT_XRES 640 | |||
//#define DEFAULT_YRES 480 | |||
//#define DEFAULT_XRES 800 | |||
//#define DEFAULT_YRES 600 | |||
//#define DEFAULT_XRES 1024 | |||
//#define DEFAULT_YRES 768 | |||
//#define DEFAULT_XRES 1280 | |||
//#define DEFAULT_YRES 720 | |||
//#define DEFAULT_XRES 1280 | |||
//#define DEFAULT_YRES 800 | |||
#define DEFAULT_XRES 1366 | |||
#define DEFAULT_YRES 768 | |||
//#define DEFAULT_XRES 1440 | |||
//#define DEFAULT_YRES 900 | |||
//#define DEFAULT_XRES 1920 | |||
//#define DEFAULT_YRES 1080 | |||
//#define DEFAULT_XRES 2560 | |||
//#define DEFAULT_YRES 1440 | |||
//#define DEFAULT_XRES 2560 | |||
//#define DEFAULT_YRES 1600 | |||
//#define DEFAULT_XRES 2880 | |||
//#define DEFAULT_YRES 1800 | |||
//#define DEFAULT_XRES 3840 | |||
//#define DEFAULT_YRES 2160 | |||
//#define DEFAULT_XRES 7680 | |||
//#define DEFAULT_YRES 4320 | |||
#define DEFAULT_XSCALE ((0x80000000ul+DEFAULT_XRES/2)/DEFAULT_XRES) | |||
#define DEFAULT_YSCALE ((0x80000000ul+DEFAULT_YRES/2)/DEFAULT_YRES) | |||
static uint16_t usb_mouse_resolution_x=DEFAULT_XRES; | |||
static uint16_t usb_mouse_resolution_y=DEFAULT_YRES; | |||
static uint16_t usb_mouse_position_x=DEFAULT_XRES/2; | |||
static uint16_t usb_mouse_position_y=DEFAULT_YRES/2; | |||
static uint32_t usb_mouse_scale_x=DEFAULT_XSCALE; | |||
static uint32_t usb_mouse_scale_y=DEFAULT_YSCALE; | |||
static uint32_t usb_mouse_offset_x=DEFAULT_XSCALE/2-1; | |||
static uint32_t usb_mouse_offset_y=DEFAULT_YSCALE/2-1; | |||
#define TX_NUM 4 | |||
#define TX_BUFSIZE 32 | |||
static transfer_t tx_transfer[TX_NUM] __attribute__ ((used, aligned(32))); | |||
DMAMEM static uint8_t txbuffer[TX_NUM * TX_BUFSIZE] __attribute__ ((aligned(32))); | |||
static uint8_t tx_head=0; | |||
#if MOUSE_SIZE > TX_BUFSIZE | |||
#error "Internal error, transmit buffer size is too small for mouse endpoint" | |||
#endif | |||
void usb_mouse_configure(void) | |||
{ | |||
memset(tx_transfer, 0, sizeof(tx_transfer)); | |||
tx_head = 0; | |||
usb_config_tx(MOUSE_ENDPOINT, MOUSE_SIZE, 0, NULL); | |||
} | |||
// Set the mouse buttons. To create a "click", 2 calls are needed, | |||
// one to push the button down and the second to release it | |||
int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t back, uint8_t forward) | |||
{ | |||
uint8_t mask=0; | |||
if (left) mask |= 1; | |||
if (middle) mask |= 4; | |||
if (right) mask |= 2; | |||
if (back) mask |= 8; | |||
if (forward) mask |= 16; | |||
usb_mouse_buttons_state = mask; | |||
return usb_mouse_move(0, 0, 0, 0); | |||
} | |||
static uint8_t transmit_previous_timeout=0; | |||
// When the PC isn't listening, how long do we wait before discarding data? | |||
#define TX_TIMEOUT_MSEC 30 | |||
static int usb_mouse_transmit(const uint8_t *data, uint32_t len) | |||
{ | |||
if (!usb_configuration) return -1; | |||
uint32_t head = tx_head; | |||
transfer_t *xfer = tx_transfer + head; | |||
uint32_t wait_begin_at = systick_millis_count; | |||
while (1) { | |||
uint32_t status = usb_transfer_status(xfer); | |||
if (!(status & 0x80)) { | |||
if (status & 0x68) { | |||
// TODO: what if status has errors??? | |||
printf("ERROR status = %x, i=%d, ms=%u\n", | |||
status, tx_head, systick_millis_count); | |||
} | |||
transmit_previous_timeout = 0; | |||
break; | |||
} | |||
if (transmit_previous_timeout) return -1; | |||
if (systick_millis_count - wait_begin_at > TX_TIMEOUT_MSEC) { | |||
// waited too long, assume the USB host isn't listening | |||
transmit_previous_timeout = 1; | |||
return -1; | |||
} | |||
if (!usb_configuration) return -1; | |||
yield(); | |||
} | |||
uint8_t *buffer = txbuffer + head * TX_BUFSIZE; | |||
memcpy(buffer, data, len); | |||
usb_prepare_transfer(xfer, buffer, len, 0); | |||
arm_dcache_flush_delete(buffer, TX_BUFSIZE); | |||
usb_transmit(MOUSE_ENDPOINT, xfer); | |||
if (++head >= TX_NUM) head = 0; | |||
tx_head = head; | |||
return 0; | |||
} | |||
// Move the mouse. x, y and wheel are -127 to 127. Use 0 for no movement. | |||
int usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t horiz) | |||
{ | |||
//printf("move\n"); | |||
if (x == -128) x = -127; | |||
if (y == -128) y = -127; | |||
if (wheel == -128) wheel = -127; | |||
if (horiz == -128) horiz = -127; | |||
uint8_t buffer[6]; | |||
buffer[0] = 1; | |||
buffer[1] = usb_mouse_buttons_state; | |||
buffer[2] = x; | |||
buffer[3] = y; | |||
buffer[4] = wheel; | |||
buffer[5] = horiz; // horizontal scroll | |||
return usb_mouse_transmit(buffer, 6); | |||
} | |||
int usb_mouse_position(uint16_t x, uint16_t y) | |||
{ | |||
if (x >= usb_mouse_resolution_x) x = usb_mouse_resolution_x - 1; | |||
usb_mouse_position_x = x; | |||
if (y >= usb_mouse_resolution_y) y = usb_mouse_resolution_y - 1; | |||
usb_mouse_position_y = y; | |||
uint8_t buffer[5]; | |||
buffer[0] = 2; | |||
uint32_t val32 = usb_mouse_position_x * usb_mouse_scale_x + usb_mouse_offset_x; | |||
//printf("position: %u -> %u", usb_mouse_position_x, val32); | |||
buffer[1] = val32 >> 16; | |||
buffer[2] = val32 >> 24; | |||
val32 = usb_mouse_position_y * usb_mouse_scale_y + usb_mouse_offset_y; | |||
//printf(", %u -> %u\n", usb_mouse_position_y, val32); | |||
buffer[3] = val32 >> 16; | |||
buffer[4] = val32 >> 24; | |||
return usb_mouse_transmit(buffer, 5); | |||
} | |||
void usb_mouse_screen_size(uint16_t width, uint16_t height, uint8_t mac) | |||
{ | |||
if (width < 128) width = 128; | |||
else if (width > 7680) width = 7680; | |||
if (height < 128) height = 128; | |||
else if (height > 7680) height = 7680; | |||
usb_mouse_resolution_x = width; | |||
usb_mouse_resolution_y = height; | |||
usb_mouse_position_x = width / 2; | |||
usb_mouse_position_y = height / 2; | |||
usb_mouse_scale_x = (0x80000000ul + (width >> 1)) / width; | |||
usb_mouse_scale_y = (0x80000000ul + (height >> 1)) / height; | |||
usb_mouse_offset_x = (usb_mouse_scale_x >> 1) - 1; | |||
usb_mouse_offset_y = (usb_mouse_scale_y >> 1) - 1; | |||
if (mac) { | |||
// ugly workaround for Mac's HID coordinate scaling: | |||
// http://lists.apple.com/archives/usb/2011/Jun/msg00032.html | |||
usb_mouse_offset_x += 161061273ul; | |||
usb_mouse_offset_y += 161061273ul; | |||
usb_mouse_scale_x = (1825361101ul + (width >> 1)) / width; | |||
usb_mouse_scale_y = (1825361101ul + (height >> 1)) / height; | |||
} | |||
} | |||
#endif // MOUSE_INTERFACE |
@@ -0,0 +1,111 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2017 PJRC.COM, LLC. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sublicense, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* 1. The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* 2. If the Software is incorporated into a build system that allows | |||
* selection among a list of target devices, then similar target | |||
* devices manufactured by PJRC.COM must be included in the list of | |||
* target devices and selectable in the same manner. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#ifndef USBmouse_h_ | |||
#define USBmouse_h_ | |||
#include "usb_desc.h" | |||
#if defined(MOUSE_INTERFACE) | |||
#include <inttypes.h> | |||
// C language implementation | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
void usb_mouse_configure(void); | |||
int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right, uint8_t back, uint8_t forward); | |||
int usb_mouse_move(int8_t x, int8_t y, int8_t wheel, int8_t horiz); | |||
int usb_mouse_position(uint16_t x, uint16_t y); | |||
void usb_mouse_screen_size(uint16_t width, uint16_t height, uint8_t mac); | |||
extern uint8_t usb_mouse_buttons_state; | |||
extern volatile uint8_t usb_configuration; | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#define MOUSE_LEFT 1 | |||
#define MOUSE_MIDDLE 4 | |||
#define MOUSE_RIGHT 2 | |||
#define MOUSE_BACK 8 | |||
#define MOUSE_FORWARD 16 | |||
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_BACK | MOUSE_FORWARD) | |||
// C++ interface | |||
#ifdef __cplusplus | |||
class usb_mouse_class | |||
{ | |||
public: | |||
void begin(void) { } | |||
void end(void) { } | |||
void move(int8_t x, int8_t y, int8_t wheel=0, int8_t horiz=0) { | |||
usb_mouse_move(x, y, wheel, horiz); | |||
} | |||
void moveTo(uint16_t x, uint16_t y) { usb_mouse_position(x, y); } | |||
void screenSize(uint16_t width, uint16_t height, bool isMacintosh = false) { | |||
usb_mouse_screen_size(width, height, isMacintosh ? 1 : 0); | |||
} | |||
void click(uint8_t b = MOUSE_LEFT) { | |||
usb_mouse_buttons_state = b; | |||
usb_mouse_move(0, 0, 0, 0); | |||
usb_mouse_buttons_state = 0; | |||
usb_mouse_move(0, 0, 0, 0); | |||
} | |||
void scroll(int8_t wheel, int8_t horiz=0) { usb_mouse_move(0, 0, wheel, horiz); } | |||
void set_buttons(uint8_t left, uint8_t middle=0, uint8_t right=0, uint8_t back=0, uint8_t forward=0) { | |||
usb_mouse_buttons(left, middle, right, back, forward); | |||
} | |||
void press(uint8_t b = MOUSE_LEFT) { | |||
uint8_t buttons = usb_mouse_buttons_state | (b & MOUSE_ALL); | |||
if (buttons != usb_mouse_buttons_state) { | |||
usb_mouse_buttons_state = buttons; | |||
usb_mouse_move(0, 0, 0, 0); | |||
} | |||
} | |||
void release(uint8_t b = MOUSE_LEFT) { | |||
uint8_t buttons = usb_mouse_buttons_state & ~(b & MOUSE_ALL); | |||
if (buttons != usb_mouse_buttons_state) { | |||
usb_mouse_buttons_state = buttons; | |||
usb_mouse_move(0, 0, 0, 0); | |||
} | |||
} | |||
bool isPressed(uint8_t b = MOUSE_ALL) { | |||
return ((usb_mouse_buttons_state & (b & MOUSE_ALL)) != 0); | |||
} | |||
}; | |||
extern usb_mouse_class Mouse; | |||
#endif // __cplusplus | |||
#endif // MOUSE_INTERFACE | |||
#endif // USBmouse_h_ |