Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Teensy 2.0 USB MIDI + MOUSE

  1. #1
    Junior Member
    Join Date
    Mar 2018
    Posts
    9

    Teensy 2.0 USB MIDI + MOUSE

    Hello

    I am trying to use encoders of my midi controller to act as mousescroll. Having read some posts I found that this one ( https://forum.pjrc.com/threads/23814-MIDI-HID-combo ) is the one that gets me closer to my goal, but I get stuck at some point…..

    I summarise what I have done so far (I followed Yeahtuna post step by step):


    1- Added these lines to boards.txt file

    Code:
    teensy2.menu.usb.midiMouse.name=MIDI + MOUSE
    teensy2.menu.usb.midiMouse.build.define0=-DUSB_MIDI_MOUSE
    teensy2.menu.usb.midiMouse.fake_serial=teensy_gateway
    As you can see I have substituted “hidMidi” (of yeahtuna example) with “midiMouse” but I have no idea if this is correct.

    2- Added these lines to teensy/usb_private.h file

    Code:
    #elif defined(USB_MIDI_MOUSE)
    #include "../usb_midi_mouse/usb_private.h"
    3- I created a copy of the “usb_midi” folder and renamed it to “usb_midi_mouse”

    4- Edited the USB_private.h in my usb_midi_mouse folder:

    Code:
    #define VENDOR_ID               0x16C0 // left unchanged
    #define PRODUCT_ID              0x0485 //changed this value from 0x0489
    #define TRANSMIT_FLUSH_TIMEOUT  4   /* in milliseconds */ // left unchanged
    #define TRANSMIT_TIMEOUT        25   /* in milliseconds */ // left unchanged
    
    #if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) // left unchanged
    
    #ifndef STR_PRODUCT // left unchanged
    #define STR_PRODUCT             L"INHKontrol" //this is the name of my controller
    #endif
    
    #define ENDPOINT0_SIZE          64
    
    #define DEBUG_INTERFACE		1
    #define DEBUG_TX_ENDPOINT	1
    #define DEBUG_TX_SIZE		64
    #define DEBUG_TX_BUFFER		EP_DOUBLE_BUFFER
    #define DEBUG_TX_INTERVAL	1
    #define DEBUG_RX_ENDPOINT	2
    #define DEBUG_RX_SIZE		32
    #define DEBUG_RX_BUFFER		EP_DOUBLE_BUFFER
    #define DEBUG_RX_INTERVAL	2
    
    #define MIDI_INTERFACE		0
    #define MIDI_TX_ENDPOINT	3
    #define MIDI_TX_SIZE		64
    #define MIDI_TX_BUFFER		EP_DOUBLE_BUFFER
    #define MIDI_RX_ENDPOINT	4
    #define MIDI_RX_SIZE		64
    #define MIDI_RX_BUFFER		EP_DOUBLE_BUFFER
    
    // ADDED MOUSE, CHANGED INTERFACE NAME TO 2 AND ENDPINT TO 5 
    
    #define MOUSE_INTERFACE		2 // changed
    #define MOUSE_ENDPOINT		5         // changed
    #define MOUSE_SIZE		8
    #define MOUSE_BUFFER		EP_DOUBLE_BUFFER
    #define MOUSE_INTERVAL		1
    
    #define NUM_ENDPOINTS		6
    #define NUM_INTERFACE		3
    
    #endif

    5- edited usb.c - added last line (mouse) respecting order of endpoints:

    Code:
    static const uint8_t PROGMEM endpoint_config_table[] = {
    	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER,
    	1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER,
    	1, EP_TYPE_BULK_IN,       EP_SIZE(MIDI_TX_SIZE) | MIDI_TX_BUFFER,
    	1, EP_TYPE_BULK_OUT,      EP_SIZE(MIDI_RX_SIZE) | MIDI_RX_BUFFER,
    	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE (MOUSE_SIZE) | MOUSE_BUFFER
    };
    I hope I have done everything correctly up to this point.
    The final part of the post is what I find hard to understand.
    Paul and Yeahtuna talk about “copying stuff into the descriptor data arrays” but I have no idea where I can copy this information from and where to paste it….

    Thanks in advance for any help.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,069
    Quote Originally Posted by Fluxia View Post
    Paul and Yeahtuna talk about “copying stuff into the descriptor data arrays” but I have no idea where I can copy this information from and where to paste it….
    When the USB host requests a descriptor, ultimately the data Teensy sends comes from an array. On 32 bit Teensy these are all located in usb_desc.c, so it's much easier to find the ones you need.

    On Teensy 2.0 there are several copies of the code. For MIDI, you can find these arrays starting on line #80 in usb.c.

    https://github.com/PaulStoffregen/co...midi/usb.c#L80

    As you can see, it's simply an array of bytes. When the host wants this descriptor, those are the bytes Teensy will transmit. You can literally change them to any bytes you wish, though of course if you tell the host your HID data is a certain format you must send packets of the correct size and the host will try to use the data as you said it is formatted.

  3. #3
    Junior Member
    Join Date
    Mar 2018
    Posts
    9
    Thank you for your reply.
    I have also looked further at Rob's usb.c file and how he has edited it.

    I have now copied the usb.c file in my "usb_midi" folder to my "usb_midi_mouse" folder and made the following changes:

    added "Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension":

    Code:
    static const uint8_t PROGMEM mouse_hid_report_desc[] = {
    	0x05, 0x01,                     // Usage Page (Generic Desktop)
    	0x09, 0x02,                     // Usage (Mouse)
    	0xA1, 0x01,                     // Collection (Application)
    	0x05, 0x09,                     //   Usage Page (Button)
    	0x19, 0x01,                     //   Usage Minimum (Button #1)
    	0x29, 0x08,                     //   Usage Maximum (Button #8)
    	0x15, 0x00,                     //   Logical Minimum (0)
    	0x25, 0x01,                     //   Logical Maximum (1)
    	0x95, 0x08,                     //   Report Count (8)
    	0x75, 0x01,                     //   Report Size (1)
    	0x81, 0x02,                     //   Input (Data, Variable, Absolute)
    	0x05, 0x01,                     //   Usage Page (Generic Desktop)
    	0x09, 0x30,                     //   Usage (X)
    	0x09, 0x31,                     //   Usage (Y)
    	0x09, 0x38,                     //   Usage (Wheel)
    	0x15, 0x81,                     //   Logical Minimum (-127)
    	0x25, 0x7F,                     //   Logical Maximum (127)
    	0x75, 0x08,                     //   Report Size (8),
    	0x95, 0x03,                     //   Report Count (3),
    	0x81, 0x06,                     //   Input (Data, Variable, Relative)
    	0x05, 0x0C,                     //   Usage Page (Consumer)
    	0x0A, 0x38, 0x02,               //   Usage (AC Pan)
    	0x15, 0x81,                     //   Logical Minimum (-127)
    	0x25, 0x7F,                     //   Logical Maximum (127)
    	0x75, 0x08,                     //   Report Size (8),
    	0x95, 0x01,                     //   Report Count (1),
    	0x81, 0x06,                     //   Input (Data, Variable, Relative)
    	0xC0                            // End Collection
    };
    added offsets:
    Code:
    #define MIDI_SIZE 74
    #define DEBUG_SIZE 32
    #define MOUSE_SIZE 25
    
    #define DEBUG_HID_DESC_OFFSET		( 9 + MIDI_SIZE + 9 )
    #define MOUSE_HID_DESC_OFFSET       ( 9 + MIDI_SIZE + DEBUG_SIZE + 9 )
    
    #define CONFIG1_DESC_SIZE		( 9 + MIDI_SIZE + DEBUG_SIZE + MOUSE_SIZE )
    finally I added the descriptor for the mouse (as the MIDI decriptor was already there having copied the midi usb.c fiole from the "usb_midi" folder):
    Code:
    // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
    		9,                                      // bLength
    		4,                                      // bDescriptorType
    		MOUSE_INTERFACE,                        // bInterfaceNumber
    		0,                                      // bAlternateSetting
    		1,                                      // bNumEndpoints
    		0x03,                                   // bInterfaceClass (0x03 = HID)
    		0x01,                                   // bInterfaceSubClass (0x01 = Boot)
    		0x02,                                   // bInterfaceProtocol (0x02 = Mouse)
    		0,                                      // iInterface
    										// HID interface descriptor, HID 1.11 spec, section 6.2.1
    		9,                                      // bLength
    		0x21,                                   // bDescriptorType
    		0x11, 0x01,                             // bcdHID
    		0,                                      // bCountryCode
    		1,                                      // bNumDescriptors
    		0x22,                                   // bDescriptorType
    		sizeof (mouse_hid_report_desc),          // wDescriptorLength
    		0,
    		// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
    		7,                                      // bLength
    		5,                                      // bDescriptorType
    		MOUSE_ENDPOINT | 0x80,                  // bEndpointAddress
    		0x03,                                   // bmAttributes (0x03=intr)
    		MOUSE_SIZE, 0,                          // wMaxPacketSize
    		MOUSE_INTERVAL,                         // bInterval
    
    };
    This still seems to be not enough to work. I do no get MIDI + MOUSE in the menu.
    I see there are other two files in my "usb_midi_mouse" folder: usb_api.cpp and usb_api.c. Do they also need editing?

  4. #4
    Junior Member
    Join Date
    Mar 2018
    Posts
    9
    I decide to improvise and copied the following lines (anything I could find related to mouse) from usb_api.cpp (hid folder) to my new usb_api.cpp (usb_midi_mouse folder) :


    Code:
    void usb_mouse_class::move (int8_t x, int8_t y, int8_t wheel, int8_t horiz)
    {
    	uint8_t intr_state, timeout;
    
    	if (!usb_configuration) return;
    	if (x == -128) x = -127;
    	if (y == -128) y = -127;
    	if (wheel == -128) wheel = -127;
    	if (horiz == -128) horiz = -127;
    	intr_state = SREG;
    	cli ();
    	UENUM = MOUSE_ENDPOINT;
    	timeout = UDFNUML + 50;
    	while (1) {
    		// are we ready to transmit?
    		if (UEINTX & (1 << RWAL)) break;
    		SREG = intr_state;
    		// has the USB gone offline?
    		if (!usb_configuration) return;
    		// have we waited too long?
    		if (UDFNUML == timeout) return;
    		// get ready to try checking again
    		intr_state = SREG;
    		cli ();
    		UENUM = MOUSE_ENDPOINT;
    	}
    	UEDATX = mouse_buttons;
    	UEDATX = x;
    	UEDATX = y;
    	UEDATX = wheel;
    	UEDATX = horiz;
    	UEINTX = 0x3A;
    	SREG = intr_state;
    }
    
    void usb_mouse_class::click (uint8_t b)
    {
    	mouse_buttons = b;
    	move (0, 0);
    	mouse_buttons = 0;
    	move (0, 0);
    }
    
    void usb_mouse_class::scroll (int8_t wheel, int8_t horiz)
    {
    	move (0, 0, wheel, horiz);
    }
    
    void usb_mouse_class::set_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;
    	mouse_buttons = mask;
    	move (0, 0);
    }
    
    void usb_mouse_class::press (uint8_t b)
    {
    	uint8_t prev = mouse_buttons;
    	mouse_buttons |= (b & 7);
    	if (mouse_buttons != prev) move (0, 0);
    }
    
    void usb_mouse_class::release (uint8_t b)
    {
    	uint8_t prev = mouse_buttons;
    	mouse_buttons &= ~(b & 7);
    	if (mouse_buttons != prev) move (0, 0);
    }
    
    bool usb_mouse_class::isPressed (uint8_t b)
    {
    	return ((mouse_buttons & (b & 7)) != 0);
    }
    
    
    // and at the end under Preinstantiate Objects //////////////////////////////////////////////////////
    
    usb_mouse_class		Mouse = usb_mouse_class ();
    same for the file usb_api.h
    added the following lines:

    Code:
    extern usb_midi_class usbMIDI;
    
    #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)
    
    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);
    	void click (uint8_t b = MOUSE_LEFT);
    	void scroll (int8_t wheel, int8_t horiz = 0);
    	void set_buttons (uint8_t left, uint8_t middle = 0, uint8_t right = 0, uint8_t back = 0, uint8_t forward = 0);
    	void press (uint8_t b = MOUSE_LEFT);
    	void release (uint8_t b = MOUSE_LEFT);
    	bool isPressed (uint8_t b = MOUSE_ALL);
    };
    
    extern usb_mouse_class Mouse;
    
    class usb_serial_class : public Stream
    {
    public:
    	// standard Arduino functions
    	void begin(long);
    	void end();
    	virtual int available();
    	virtual int read();
    	virtual int peek();
    	virtual void flush();
    #if ARDUINO >= 100
    	virtual size_t write(uint8_t);
    #else
    	virtual void write(uint8_t);
    #endif
    	using Print::write;
    	operator bool();
    	// Teensy extensions
    	void send_now(void);
    	uint32_t baud(void);
    	uint8_t stopbits(void);
    	uint8_t paritytype(void);
    	uint8_t numbits(void);
    	uint8_t dtr(void);
    	uint8_t rts(void);
    private:
    	uint8_t readnext(void);
    };
    
    extern usb_serial_class Serial;
    finally I added the following lines to the usb.c file (the one in the core/teensy directory):

    Code:
    #elif defined(USB_MIDI_MOUSE)
    #include "../usb_midi_mouse/usb.c"
    However, when select teensy 2.0 in the arduino IDE and I go to tool - USB type, "MIDI + MOUSE" is not there. Not sure there is anything more I can do without some guidance.

  5. #5
    Junior Member
    Join Date
    Mar 2018
    Posts
    9
    I have now managed to fix the menu issue by changing the lines in "boards.txt" from this:

    Code:
    teensy2.menu.usb.midiMouse.name=MIDI + MOUSE
    teensy2.menu.usb.midiMouse.build.define0=-DUSB_MIDI_MOUSE
    teensy2.menu.usb.midiMouse.fake_serial=teensy_gateway
    to this:

    Code:
    teensy2.menu.usb.midiMouse=MIDI + MOUSE
    teensy2.menu.usb.midiMouse.build.usbtype=USB_MIDI_MOUSE
    teensy2.menu.usb.midiMouse.fake_serial=teensy_gateway
    Now I finally gets the new option in the menu but I got a "not declared in this scope" error messages when compiling.

    I looked at the following files:

    1 - core_id.h
    I added:

    Code:
    #elif defined(USB_MIDI_MOUSE)
    #include "../usb_midi_mouse/core_id.h"
    2 - usb_api.cpp
    I added:

    Code:
    #elif defined(USB_MIDI_MOUSE)
    #include "../usb_midi_mouse/usb_api.cpp"
    3 - usb_api.h
    I added:

    Code:
    #elif defined(USB_MIDI_MOUSE)
    #include "../usb_midi_mouse/usb_api.h"
    It starts compiling but gets error messages that apparently are related to "usb_api.cpp" file.

    this is the message:


    In file included from E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\usb _api.cpp:12:0:

    Code:
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'void usb_mouse_class::move(int8_t, int8_t, int8_t, int8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:467:11: error: 'mouse_buttons' was not declared in this scope
    
      UEDATX = mouse_buttons;
    
               ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'void usb_mouse_class::click(uint8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:478:2: error: 'mouse_buttons' was not declared in this scope
    
      mouse_buttons = b;
    
      ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'void usb_mouse_class::set_buttons(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:498:2: error: 'mouse_buttons' was not declared in this scope
    
      mouse_buttons = mask;
    
      ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'void usb_mouse_class::press(uint8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:504:17: error: 'mouse_buttons' was not declared in this scope
    
      uint8_t prev = mouse_buttons;
    
                     ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'void usb_mouse_class::release(uint8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:511:17: error: 'mouse_buttons' was not declared in this scope
    
      uint8_t prev = mouse_buttons;
    
                     ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp: In member function 'bool usb_mouse_class::isPressed(uint8_t)':
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:518:11: error: 'mouse_buttons' was not declared in this scope
    
      return ((mouse_buttons & (b & 7)) != 0);
    
               ^
    
    E:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy\../usb_midi_mouse/usb_api.cpp:519:1: warning: control reaches end of non-void function [-Wreturn-type]
    
     }
    
     ^
    
    Error compiling for board Teensy 2.0.
    I will now look into it ... keep trying ...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •