3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -4,3 +4,6 @@
 | 
			
		||||
[submodule "hw/mcu/microchip/samd/asf4"]
 | 
			
		||||
	path = hw/mcu/microchip/samd/asf4
 | 
			
		||||
	url = https://github.com/adafruit/asf4.git
 | 
			
		||||
[submodule "tests/vendor/unity"]
 | 
			
		||||
	path = tests/vendor/unity
 | 
			
		||||
	url = https://github.com/ThrowTheSwitch/Unity.git
 | 
			
		||||
 
 | 
			
		||||
@@ -19,3 +19,4 @@ before_script:
 | 
			
		||||
script:
 | 
			
		||||
  - make -j2 -C examples/device/cdc_msc_hid BOARD=metro_m0_express
 | 
			
		||||
  - make -j2 -C examples/device/cdc_msc_hid BOARD=metro_m4_express
 | 
			
		||||
  - cd tests/common && make
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +109,7 @@
 | 
			
		||||
//------------- CLASS -------------//
 | 
			
		||||
#define CFG_TUD_CDC                 1
 | 
			
		||||
#define CFG_TUD_MSC                 1
 | 
			
		||||
#define CFG_TUD_MIDI                0
 | 
			
		||||
#define CFG_TUD_CUSTOM_CLASS        0
 | 
			
		||||
 | 
			
		||||
#define CFG_TUD_HID                 0
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								src/class/audio/audio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/class/audio/audio.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     cdc.h
 | 
			
		||||
    @author   hathach (tinyusb.org)
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2013, hathach (tinyusb.org)
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
    This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
/** \ingroup group_class
 | 
			
		||||
 *  \defgroup ClassDriver_Audio Audio
 | 
			
		||||
 *            Currently only MIDI subclass is supported
 | 
			
		||||
 *  @{ */
 | 
			
		||||
 | 
			
		||||
#ifndef _TUSB_CDC_H__
 | 
			
		||||
#define _TUSB_CDC_H__
 | 
			
		||||
 | 
			
		||||
#include "common/tusb_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/// Audio Interface Subclass Codes
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  AUDIO_SUBCLASS_AUDIO_CONTROL = 0x01  , ///< Audio Control
 | 
			
		||||
  AUDIO_SUBCLASS_AUDIO_STREAMING       , ///< Audio Streaming
 | 
			
		||||
  AUDIO_SUBCLASS_MIDI_STREAMING       ,  ///< MIDI Streaming
 | 
			
		||||
} audio_subclass_type_t;
 | 
			
		||||
 | 
			
		||||
/// Audio Protocol Codes
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  AUDIO_PROTOCOL_V1                   = 0x00, ///< Version 1.0
 | 
			
		||||
  AUDIO_PROTOCOL_V2                   = 0x20, ///< Version 2.0
 | 
			
		||||
  AUDIO_PROTOCOL_V3                   = 0x30, ///< Version 3.0
 | 
			
		||||
} audio_protocol_type_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
							
								
								
									
										84
									
								
								src/class/midi/midi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/class/midi/midi.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     cdc.h
 | 
			
		||||
    @author   hathach (tinyusb.org)
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2013, hathach (tinyusb.org)
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
    This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
/** \ingroup group_class
 | 
			
		||||
 *  \defgroup ClassDriver_CDC Communication Device Class (CDC)
 | 
			
		||||
 *            Currently only Abstract Control Model subclass is supported
 | 
			
		||||
 *  @{ */
 | 
			
		||||
 | 
			
		||||
#ifndef _TUSB_MIDI_H__
 | 
			
		||||
#define _TUSB_MIDI_H__
 | 
			
		||||
 | 
			
		||||
#include "common/tusb_common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// FUNCTIONAL DESCRIPTOR (COMMUNICATION INTERFACE)
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
/// Header Functional Descriptor (Communication Interface)
 | 
			
		||||
typedef struct ATTR_PACKED
 | 
			
		||||
{
 | 
			
		||||
  uint8_t bLength            ; ///< Size of this descriptor in bytes.
 | 
			
		||||
  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
 | 
			
		||||
  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above MIDI_FUCN_DESC_
 | 
			
		||||
  uint16_t bcdMSC            ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal
 | 
			
		||||
  uint16_t wTotalLength      ;
 | 
			
		||||
}midi_desc_func_header_t;
 | 
			
		||||
 | 
			
		||||
/// Union Functional Descriptor (Communication Interface)
 | 
			
		||||
typedef struct ATTR_PACKED
 | 
			
		||||
{
 | 
			
		||||
  uint8_t bLength                  ; ///< Size of this descriptor in bytes.
 | 
			
		||||
  uint8_t bDescriptorType          ; ///< Descriptor Type, must be Class-Specific
 | 
			
		||||
  uint8_t bDescriptorSubType       ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
 | 
			
		||||
  uint8_t bControlInterface        ; ///< Interface number of Communication Interface
 | 
			
		||||
  uint8_t bSubordinateInterface    ; ///< Array of Interface number of Data Interface
 | 
			
		||||
}cdc_desc_func_union_t;
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
							
								
								
									
										346
									
								
								src/class/midi/midi_device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								src/class/midi/midi_device.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,346 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     cdc_device.c
 | 
			
		||||
    @author   hathach (tinyusb.org)
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2013, hathach (tinyusb.org)
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
    This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "tusb_option.h"
 | 
			
		||||
 | 
			
		||||
#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_MIDI)
 | 
			
		||||
 | 
			
		||||
#define _TINY_USB_SOURCE_FILE_
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// INCLUDE
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
#include "midi_device.h"
 | 
			
		||||
#include "class/audio/audio.h"
 | 
			
		||||
#include "common/tusb_txbuf.h"
 | 
			
		||||
#include "device/usbd_pvt.h"
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// MACRO CONSTANT TYPEDEF
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  uint8_t itf_num;
 | 
			
		||||
  uint8_t ep_in;
 | 
			
		||||
  uint8_t ep_out;
 | 
			
		||||
 | 
			
		||||
  // FIFO
 | 
			
		||||
  tu_fifo_t rx_ff;
 | 
			
		||||
  uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE];
 | 
			
		||||
  osal_mutex_def_t rx_ff_mutex;
 | 
			
		||||
 | 
			
		||||
  #if CFG_TUD_MIDI_TX_BUFSIZE % CFG_TUD_MIDI_EPSIZE != 0
 | 
			
		||||
  #error "TX buffer size must be multiple of endpoint size."
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // This is a ring buffer that aligns to word boundaries so that it can be transferred directly to
 | 
			
		||||
  // the USB peripheral. There are three states to the data: free, transmitting and pending.
 | 
			
		||||
  CFG_TUSB_MEM_ALIGN uint8_t raw_tx_buffer[CFG_TUD_MIDI_TX_BUFSIZE];
 | 
			
		||||
  tu_txbuf_t txbuf;
 | 
			
		||||
 | 
			
		||||
  // We need to pack messages into words before queueing their transmission so buffer across write
 | 
			
		||||
  // calls.
 | 
			
		||||
  uint8_t message_buffer[4];
 | 
			
		||||
  uint8_t message_buffer_length;
 | 
			
		||||
  uint8_t message_target_length;
 | 
			
		||||
 | 
			
		||||
  // Endpoint Transfer buffer
 | 
			
		||||
  CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE];
 | 
			
		||||
 | 
			
		||||
} midid_interface_t;
 | 
			
		||||
 | 
			
		||||
#define ITF_MEM_RESET_SIZE   offsetof(midid_interface_t, rx_ff)
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// INTERNAL OBJECT & FUNCTION DECLARATION
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
CFG_TUSB_ATTR_USBRAM midid_interface_t _midid_itf[CFG_TUD_MIDI];
 | 
			
		||||
 | 
			
		||||
bool tud_midi_n_connected(uint8_t itf) {
 | 
			
		||||
  midid_interface_t* midi = &_midid_itf[itf];
 | 
			
		||||
  return midi->itf_num != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// READ API
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id)
 | 
			
		||||
{
 | 
			
		||||
  return tu_fifo_count(&_midid_itf[itf].rx_ff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char tud_midi_n_read_char(uint8_t itf, uint8_t jack_id)
 | 
			
		||||
{
 | 
			
		||||
  char ch;
 | 
			
		||||
  return tu_fifo_read(&_midid_itf[itf].rx_ff, &ch) ? ch : (-1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
 | 
			
		||||
{
 | 
			
		||||
  return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
 | 
			
		||||
{
 | 
			
		||||
  tu_fifo_clear(&_midid_itf[itf].rx_ff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
 | 
			
		||||
  if (bufsize % 4 != 0) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for(uint32_t i=0; i<bufsize; i += 4) {
 | 
			
		||||
    uint8_t header = buffer[i];
 | 
			
		||||
    // uint8_t cable_number = (header & 0xf0) >> 4;
 | 
			
		||||
    uint8_t code_index = header & 0x0f;
 | 
			
		||||
    // We always copy over the first byte.
 | 
			
		||||
    uint8_t count = 1;
 | 
			
		||||
    // Ignore subsequent bytes based on the code.
 | 
			
		||||
    if (code_index != 0x5 && code_index != 0xf) {
 | 
			
		||||
      count = 2;
 | 
			
		||||
      if (code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd) {
 | 
			
		||||
        count = 3;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    tu_fifo_write_n(&midi->rx_ff, &buffer[i + 1], count);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// WRITE API
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
 | 
			
		||||
{
 | 
			
		||||
  midid_interface_t* midi = &_midid_itf[itf];
 | 
			
		||||
  if (midi->itf_num == 0) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
  while (i < bufsize) {
 | 
			
		||||
    uint8_t data = buffer[i];
 | 
			
		||||
    if (midi->message_buffer_length == 0) {
 | 
			
		||||
        uint8_t msg = data >> 4;
 | 
			
		||||
        midi->message_buffer[1] = data;
 | 
			
		||||
        midi->message_buffer_length = 2;
 | 
			
		||||
        // Check to see if we're still in a SysEx transmit.
 | 
			
		||||
        if (midi->message_buffer[0] == 0x4) {
 | 
			
		||||
            if (data == 0xf7) {
 | 
			
		||||
                midi->message_buffer[0] = 0x5;
 | 
			
		||||
            } else {
 | 
			
		||||
                midi->message_buffer_length = 4;
 | 
			
		||||
            }
 | 
			
		||||
        } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
 | 
			
		||||
            midi->message_buffer[0] = jack_id << 4 | msg;
 | 
			
		||||
            midi->message_target_length = 4;
 | 
			
		||||
        } else if (msg == 0xf) {
 | 
			
		||||
            if (data == 0xf0) {
 | 
			
		||||
                midi->message_buffer[0] = 0x4;
 | 
			
		||||
                midi->message_target_length = 4;
 | 
			
		||||
            } else if (data == 0xf1 || data == 0xf3) {
 | 
			
		||||
                midi->message_buffer[0] = 0x2;
 | 
			
		||||
                midi->message_target_length = 3;
 | 
			
		||||
            } else if (data == 0xf2) {
 | 
			
		||||
                midi->message_buffer[0] = 0x3;
 | 
			
		||||
                midi->message_target_length = 4;
 | 
			
		||||
            } else {
 | 
			
		||||
                midi->message_buffer[0] = 0x5;
 | 
			
		||||
                midi->message_target_length = 2;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Pack individual bytes if we don't support packing them into words.
 | 
			
		||||
            midi->message_buffer[0] = jack_id << 4 | 0xf;
 | 
			
		||||
            midi->message_buffer[2] = 0;
 | 
			
		||||
            midi->message_buffer[3] = 0;
 | 
			
		||||
            midi->message_buffer_length = 2;
 | 
			
		||||
            midi->message_target_length = 2;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        midi->message_buffer[midi->message_buffer_length] = data;
 | 
			
		||||
        midi->message_buffer_length += 1;
 | 
			
		||||
        // See if this byte ends a SysEx.
 | 
			
		||||
        if (midi->message_buffer[0] == 0x4 && data == 0xf7) {
 | 
			
		||||
            midi->message_buffer[0] = 0x4 + (midi->message_buffer_length - 1);
 | 
			
		||||
            midi->message_target_length = midi->message_buffer_length;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (midi->message_buffer_length == midi->message_target_length) {
 | 
			
		||||
        tu_txbuf_write_n(&midi->txbuf, midi->message_buffer, 4);
 | 
			
		||||
        midi->message_buffer_length = 0;
 | 
			
		||||
    }
 | 
			
		||||
    i++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// USBD Driver API
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
void midid_init(void)
 | 
			
		||||
{
 | 
			
		||||
  tu_memclr(_midid_itf, sizeof(_midid_itf));
 | 
			
		||||
 | 
			
		||||
  for(uint8_t i=0; i<CFG_TUD_MIDI; i++)
 | 
			
		||||
  {
 | 
			
		||||
    midid_interface_t* midi = &_midid_itf[i];
 | 
			
		||||
 | 
			
		||||
    // config fifo
 | 
			
		||||
    tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true);
 | 
			
		||||
    #if CFG_FIFO_MUTEX
 | 
			
		||||
    tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex));
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    tu_txbuf_config(&midi->txbuf, midi->raw_tx_buffer, CFG_TUD_MIDI_TX_BUFSIZE, dcd_edpt_xfer);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void midid_reset(uint8_t rhport)
 | 
			
		||||
{
 | 
			
		||||
  (void) rhport;
 | 
			
		||||
 | 
			
		||||
  for(uint8_t i=0; i<CFG_TUD_MIDI; i++)
 | 
			
		||||
  {
 | 
			
		||||
    midid_interface_t* midi = &_midid_itf[i];
 | 
			
		||||
    tu_memclr(midi, ITF_MEM_RESET_SIZE);
 | 
			
		||||
    tu_fifo_clear(&midi->rx_ff);
 | 
			
		||||
    tu_txbuf_clear(&midi->txbuf);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length)
 | 
			
		||||
{
 | 
			
		||||
  // For now handle the audio control interface as well.
 | 
			
		||||
  if ( AUDIO_SUBCLASS_AUDIO_CONTROL == p_interface_desc->bInterfaceSubClass) {
 | 
			
		||||
    uint8_t const * p_desc = tu_desc_next ( (uint8_t const *) p_interface_desc );
 | 
			
		||||
    (*p_length) = sizeof(tusb_desc_interface_t);
 | 
			
		||||
 | 
			
		||||
    // Skip over the class specific descriptor.
 | 
			
		||||
    (*p_length) += p_desc[DESC_OFFSET_LEN];
 | 
			
		||||
    p_desc = tu_desc_next(p_desc);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ( AUDIO_SUBCLASS_MIDI_STREAMING != p_interface_desc->bInterfaceSubClass ||
 | 
			
		||||
       p_interface_desc->bInterfaceProtocol != AUDIO_PROTOCOL_V1 ) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Find available interface
 | 
			
		||||
  midid_interface_t * p_midi = NULL;
 | 
			
		||||
  for(uint8_t i=0; i<CFG_TUD_MIDI; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if ( _midid_itf[i].ep_in == 0 && _midid_itf[i].ep_out == 0 )
 | 
			
		||||
    {
 | 
			
		||||
      p_midi = &_midid_itf[i];
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  p_midi->itf_num  = p_interface_desc->bInterfaceNumber;
 | 
			
		||||
 | 
			
		||||
  uint8_t const * p_desc = tu_desc_next( (uint8_t const *) p_interface_desc );
 | 
			
		||||
  (*p_length) = sizeof(tusb_desc_interface_t);
 | 
			
		||||
 | 
			
		||||
  uint8_t found_endpoints = 0;
 | 
			
		||||
  while (found_endpoints < p_interface_desc->bNumEndpoints) {
 | 
			
		||||
    if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
 | 
			
		||||
    {
 | 
			
		||||
        TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), false);
 | 
			
		||||
        uint8_t ep_addr = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
 | 
			
		||||
        if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
 | 
			
		||||
            p_midi->ep_in = ep_addr;
 | 
			
		||||
            tu_txbuf_set_ep_addr(&p_midi->txbuf, ep_addr);
 | 
			
		||||
        } else {
 | 
			
		||||
            p_midi->ep_out = ep_addr;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        (*p_length) += p_desc[DESC_OFFSET_LEN];
 | 
			
		||||
        p_desc = tu_desc_next(p_desc);
 | 
			
		||||
        found_endpoints += 1;
 | 
			
		||||
    }
 | 
			
		||||
    (*p_length) += p_desc[DESC_OFFSET_LEN];
 | 
			
		||||
    p_desc = tu_desc_next(p_desc);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Prepare for incoming data
 | 
			
		||||
  TU_ASSERT( dcd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool midid_control_request_complete(uint8_t rhport, tusb_control_request_t const * p_request)
 | 
			
		||||
{
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool midid_control_request(uint8_t rhport, tusb_control_request_t const * p_request)
 | 
			
		||||
{
 | 
			
		||||
  //------------- Class Specific Request -------------//
 | 
			
		||||
  if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return false;
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool midid_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes)
 | 
			
		||||
{
 | 
			
		||||
  // TODO Support multiple interfaces
 | 
			
		||||
  uint8_t const itf = 0;
 | 
			
		||||
  midid_interface_t* p_midi = &_midid_itf[itf];
 | 
			
		||||
 | 
			
		||||
  // receive new data
 | 
			
		||||
  if ( edpt_addr == p_midi->ep_out )
 | 
			
		||||
  {
 | 
			
		||||
    midi_rx_done_cb(p_midi, p_midi->epout_buf, xferred_bytes);
 | 
			
		||||
 | 
			
		||||
    // prepare for next
 | 
			
		||||
    TU_ASSERT( dcd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EPSIZE), false );
 | 
			
		||||
  } else if ( edpt_addr == p_midi->ep_in ) {
 | 
			
		||||
    tu_txbuf_transmit_done_cb(&p_midi->txbuf, xferred_bytes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // nothing to do with in and notif endpoint
 | 
			
		||||
 | 
			
		||||
  return TUSB_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										120
									
								
								src/class/midi/midi_device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/class/midi/midi_device.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     midi_device.h
 | 
			
		||||
    @author   hathach (tinyusb.org)
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2013, hathach (tinyusb.org)
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
    This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef _TUSB_MIDI_DEVICE_H_
 | 
			
		||||
#define _TUSB_MIDI_DEVICE_H_
 | 
			
		||||
 | 
			
		||||
#include "common/tusb_common.h"
 | 
			
		||||
#include "device/usbd.h"
 | 
			
		||||
#include "class/audio/audio.h"
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// Class Driver Configuration
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
#ifndef CFG_TUD_MIDI_EPSIZE
 | 
			
		||||
#define CFG_TUD_MIDI_EPSIZE 64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \addtogroup MIDI_Serial Serial
 | 
			
		||||
 *  @{
 | 
			
		||||
 *  \defgroup   MIDI_Serial_Device Device
 | 
			
		||||
 *  @{ */
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// APPLICATION API (Multiple Interfaces)
 | 
			
		||||
// CFG_TUD_MIDI > 1
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
bool     tud_midi_n_connected       (uint8_t itf);
 | 
			
		||||
 | 
			
		||||
uint32_t tud_midi_n_available       (uint8_t itf, uint8_t jack_id);
 | 
			
		||||
char     tud_midi_n_read_char       (uint8_t itf, uint8_t jack_id);
 | 
			
		||||
uint32_t tud_midi_n_read            (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize);
 | 
			
		||||
void     tud_midi_n_read_flush      (uint8_t itf, uint8_t jack_id);
 | 
			
		||||
char     tud_midi_n_peek            (uint8_t itf, uint8_t jack_id, int pos);
 | 
			
		||||
 | 
			
		||||
uint32_t tud_midi_n_write_char      (uint8_t itf, char ch);
 | 
			
		||||
uint32_t tud_midi_n_write           (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
 | 
			
		||||
bool     tud_midi_n_write_flush     (uint8_t itf);
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// APPLICATION API (Interface0)
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
static inline bool     tud_midi_connected       (void)                                 { return tud_midi_n_connected(0);              }
 | 
			
		||||
 | 
			
		||||
static inline uint32_t tud_midi_available       (void)                                 { return tud_midi_n_available(0, 0);              }
 | 
			
		||||
static inline char     tud_midi_read_char       (void)                                 { return tud_midi_n_read_char(0, 0);              }
 | 
			
		||||
static inline uint32_t tud_midi_read            (void* buffer, uint32_t bufsize)       { return tud_midi_n_read(0, 0, buffer, bufsize);  }
 | 
			
		||||
static inline void     tud_midi_read_flush      (void)                                 { tud_midi_n_read_flush(0, 0);                    }
 | 
			
		||||
static inline char     tud_midi_peek            (int pos)                              { return tud_midi_n_peek(0, 0, pos);              }
 | 
			
		||||
 | 
			
		||||
static inline uint32_t tud_midi_write_char      (char ch)                              { return tud_midi_n_write_char(0, ch);         }
 | 
			
		||||
static inline uint32_t tud_midi_write           (uint8_t jack_id, void const* buffer, uint32_t bufsize) { return tud_midi_n_write(0, jack_id, buffer, bufsize); }
 | 
			
		||||
static inline bool     tud_midi_write_flush     (void)                                 { return tud_midi_n_write_flush(0);            }
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// APPLICATION CALLBACK API (WEAK is optional)
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
ATTR_WEAK void tud_midi_rx_cb(uint8_t itf);
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// USBD-CLASS DRIVER API
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
#ifdef _TINY_USB_SOURCE_FILE_
 | 
			
		||||
 | 
			
		||||
void         midid_init               (void);
 | 
			
		||||
bool midid_open               (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
 | 
			
		||||
bool midid_control_request (uint8_t rhport, tusb_control_request_t const * p_request);
 | 
			
		||||
bool midid_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request);
 | 
			
		||||
bool midid_xfer_cb            (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes);
 | 
			
		||||
void         midid_reset              (uint8_t rhport);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _TUSB_MIDI_DEVICE_H_ */
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
/** @} */
 | 
			
		||||
							
								
								
									
										159
									
								
								src/common/tusb_txbuf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/common/tusb_txbuf.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     tusb_txbuf.c
 | 
			
		||||
    @author   Scott Shawcroft
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2018, Scott Shawcroft
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
 This file is part of the tinyusb stack.
 | 
			
		||||
 */
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "tusb_txbuf.h"
 | 
			
		||||
 | 
			
		||||
bool tu_txbuf_config(tu_txbuf_t *txbuf, uint8_t* buffer, uint16_t buffer_length, edpt_xfer xfer)
 | 
			
		||||
{
 | 
			
		||||
  txbuf->buffer = (uint8_t*) buffer;
 | 
			
		||||
  txbuf->buf_len = buffer_length;
 | 
			
		||||
  txbuf->first_free = 0;
 | 
			
		||||
  txbuf->pending_count = 0;
 | 
			
		||||
  txbuf->transmitting_count = 0;
 | 
			
		||||
  txbuf->xfer = xfer;
 | 
			
		||||
  txbuf->padding = 0;
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t maybe_transmit(tu_txbuf_t* buf) {
 | 
			
		||||
    if (buf->transmitting_count > 0 || buf->pending_count == 0) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    buf->transmitting_count = buf->pending_count;
 | 
			
		||||
    uint16_t transmit_start_index;
 | 
			
		||||
    uint8_t over_aligned = 0;
 | 
			
		||||
    // The pending zone wraps back to the end so we must do two transfers.
 | 
			
		||||
    if (buf->pending_count > buf->first_free) {
 | 
			
		||||
        buf->transmitting_count -= buf->first_free;
 | 
			
		||||
        transmit_start_index = buf->buf_len - buf->transmitting_count;
 | 
			
		||||
    } else {
 | 
			
		||||
        transmit_start_index = buf->first_free - buf->transmitting_count;
 | 
			
		||||
 | 
			
		||||
        // We are transmitting up to first free so ensure it's word aligned for the next transmit.
 | 
			
		||||
        over_aligned = buf->first_free % sizeof(uint32_t);
 | 
			
		||||
        buf->padding = sizeof(uint32_t) - over_aligned;
 | 
			
		||||
        if (over_aligned != 0) {
 | 
			
		||||
            buf->first_free = (buf->first_free + buf->padding) % buf->buf_len;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    buf->pending_count -= buf->transmitting_count;
 | 
			
		||||
 | 
			
		||||
    uint8_t* tx_start = buf->buffer + transmit_start_index;
 | 
			
		||||
    if (!buf->xfer(0, buf->ep_addr, tx_start, buf->transmitting_count)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return buf->transmitting_count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t tu_txbuf_transmit_done_cb(tu_txbuf_t* buf, uint32_t bufsize) {
 | 
			
		||||
    buf->transmitting_count -= bufsize;
 | 
			
		||||
 | 
			
		||||
    return maybe_transmit(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @brief This function will write n elements into the array index specified by
 | 
			
		||||
    the write pointer and increment the write index. If the write index
 | 
			
		||||
    exceeds the max buffer size, then it will roll over to zero.
 | 
			
		||||
 | 
			
		||||
    @param[in]  f
 | 
			
		||||
                Pointer to the FIFO buffer to manipulate
 | 
			
		||||
    @param[in]  p_data
 | 
			
		||||
                The pointer to data to add to the FIFO
 | 
			
		||||
    @param[in]  count
 | 
			
		||||
                Number of element
 | 
			
		||||
    @return Number of written elements
 | 
			
		||||
*/
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
uint16_t tu_txbuf_write_n(tu_txbuf_t* txbuf, uint8_t const* buffer, uint32_t bufsize) {
 | 
			
		||||
    uint32_t len;
 | 
			
		||||
    int32_t last_free = txbuf->first_free - txbuf->pending_count - txbuf->transmitting_count - txbuf->padding;
 | 
			
		||||
    if (last_free < 0) {
 | 
			
		||||
        last_free += txbuf->buf_len;
 | 
			
		||||
        len = last_free - txbuf->first_free;
 | 
			
		||||
    } else {
 | 
			
		||||
        len = txbuf->buf_len - txbuf->first_free;
 | 
			
		||||
    }
 | 
			
		||||
    if (bufsize < len) {
 | 
			
		||||
        len = bufsize;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(txbuf->buffer + txbuf->first_free, buffer, len);
 | 
			
		||||
    txbuf->first_free = (txbuf->first_free + len) % txbuf->buf_len;
 | 
			
		||||
    txbuf->pending_count += len;
 | 
			
		||||
    // Try to transmit now while we wrap the rest.
 | 
			
		||||
    maybe_transmit(txbuf);
 | 
			
		||||
    uint32_t remaining_bytes = bufsize - len;
 | 
			
		||||
    if (remaining_bytes > 0 && last_free != txbuf->first_free) {
 | 
			
		||||
        uint32_t second_len = remaining_bytes;
 | 
			
		||||
        if (second_len > (uint32_t) last_free + 1) {
 | 
			
		||||
            second_len = last_free + 1;
 | 
			
		||||
        }
 | 
			
		||||
        memcpy(txbuf->buffer, buffer + len, second_len);
 | 
			
		||||
        txbuf->first_free = (txbuf->first_free + second_len) % txbuf->buf_len;
 | 
			
		||||
        txbuf->pending_count += second_len;
 | 
			
		||||
        len += second_len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tu_txbuf_set_ep_addr(tu_txbuf_t* txbuf, uint8_t ep_addr) {
 | 
			
		||||
    txbuf->ep_addr = ep_addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @brief Clear the txbuf including any currently transmitting data.
 | 
			
		||||
 | 
			
		||||
    @param[in]  t
 | 
			
		||||
                Pointer to the txbuf to manipulate
 | 
			
		||||
*/
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
bool tu_txbuf_clear(tu_txbuf_t *txbuf)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  txbuf->first_free = 0;
 | 
			
		||||
  txbuf->pending_count = 0;
 | 
			
		||||
  txbuf->transmitting_count = 0;
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								src/common/tusb_txbuf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/common/tusb_txbuf.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     tusb_txbuf.h
 | 
			
		||||
    @author   Scott Shawcroft
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2018, Scott Shawcroft
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
	  This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
/** \ingroup Group_Common
 | 
			
		||||
 * \defgroup group_txbuf txbuf
 | 
			
		||||
 *  @{ */
 | 
			
		||||
 | 
			
		||||
#ifndef _TUSB_TXBUF_H_
 | 
			
		||||
#define _TUSB_TXBUF_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef bool (*edpt_xfer) (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** \struct tu_txbuf_t
 | 
			
		||||
 * \brief Circular transmit buffer that manages USB transfer memory. It is not threadsafe and is
 | 
			
		||||
 *        only meant for use in the main task.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* buffer    ; ///< buffer pointer
 | 
			
		||||
    uint16_t buf_len;
 | 
			
		||||
    uint16_t first_free;
 | 
			
		||||
    uint16_t pending_count;
 | 
			
		||||
    uint16_t transmitting_count;
 | 
			
		||||
    uint16_t padding;
 | 
			
		||||
    uint8_t ep_addr;
 | 
			
		||||
    edpt_xfer xfer;
 | 
			
		||||
} tu_txbuf_t;
 | 
			
		||||
 | 
			
		||||
bool tu_txbuf_clear(tu_txbuf_t *f);
 | 
			
		||||
bool tu_txbuf_config(tu_txbuf_t *f, uint8_t* buffer, uint16_t depth, edpt_xfer xfer);
 | 
			
		||||
 | 
			
		||||
uint16_t tu_txbuf_write_n (tu_txbuf_t* txbuf, uint8_t const * buffer, uint32_t length);
 | 
			
		||||
void tu_txbuf_set_ep_addr(tu_txbuf_t* txbuf, uint8_t ep_addr);
 | 
			
		||||
uint32_t tu_txbuf_transmit_done_cb(tu_txbuf_t* buf, uint32_t bufsize);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _TUSB_TXBUF_H_ */
 | 
			
		||||
@@ -128,6 +128,19 @@ static usbd_class_driver_t const usbd_class_drivers[] =
 | 
			
		||||
    },
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if CFG_TUD_MIDI
 | 
			
		||||
    {
 | 
			
		||||
        .class_code      = TUSB_CLASS_AUDIO,
 | 
			
		||||
        .init            = midid_init,
 | 
			
		||||
        .open            = midid_open,
 | 
			
		||||
        .control_request = midid_control_request,
 | 
			
		||||
        .control_request_complete = midid_control_request_complete,
 | 
			
		||||
        .xfer_cb         = midid_xfer_cb,
 | 
			
		||||
        .sof             = NULL,
 | 
			
		||||
        .reset           = midid_reset
 | 
			
		||||
    },
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if CFG_TUD_CUSTOM_CLASS
 | 
			
		||||
    {
 | 
			
		||||
        .class_code      = TUSB_CLASS_VENDOR_SPECIFIC,
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,10 @@
 | 
			
		||||
    #include "class/msc/msc_device.h"
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if CFG_TUD_MIDI
 | 
			
		||||
    #include "class/midi/midi_device.h"
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if CFG_TUD_CUSTOM_CLASS
 | 
			
		||||
    #include "class/custom/custom_device.h"
 | 
			
		||||
  #endif
 | 
			
		||||
@@ -128,4 +132,3 @@ static inline void tusb_task(void)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _TUSB_H_ */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										91
									
								
								tests/common/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								tests/common/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
ifeq ($(OS),Windows_NT)
 | 
			
		||||
  ifeq ($(shell uname -s),) # not in a bash-like shell
 | 
			
		||||
	CLEANUP = del /F /Q
 | 
			
		||||
	MKDIR = mkdir
 | 
			
		||||
  else # in a bash-like shell, like msys
 | 
			
		||||
	CLEANUP = rm -f
 | 
			
		||||
	MKDIR = mkdir -p
 | 
			
		||||
  endif
 | 
			
		||||
	TARGET_EXTENSION=.exe
 | 
			
		||||
else
 | 
			
		||||
	CLEANUP = rm -f
 | 
			
		||||
	MKDIR = mkdir -p
 | 
			
		||||
	TARGET_EXTENSION=out
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
.PHONY: test
 | 
			
		||||
 | 
			
		||||
PATHU = ../vendor/unity/src/
 | 
			
		||||
PATHS = ../../src/
 | 
			
		||||
PATHT = test/
 | 
			
		||||
PATHB = build/
 | 
			
		||||
PATHD = build/depends/
 | 
			
		||||
PATHO = build/objs/
 | 
			
		||||
PATHR = build/results/
 | 
			
		||||
 | 
			
		||||
BUILD_PATHS = $(PATHB) $(PATHD) $(PATHO) $(PATHR)
 | 
			
		||||
 | 
			
		||||
SRCT = $(wildcard $(PATHT)*.c)
 | 
			
		||||
 | 
			
		||||
$(info $(SRCT))
 | 
			
		||||
 | 
			
		||||
COMPILE=gcc -c
 | 
			
		||||
LINK=gcc
 | 
			
		||||
DEPEND=gcc -MM -MG -MF
 | 
			
		||||
CFLAGS=-I. -I$(PATHU) -I$(PATHS) -DTEST
 | 
			
		||||
 | 
			
		||||
RESULTS = $(patsubst $(PATHT)test%.c,$(PATHR)test%.txt,$(SRCT) )
 | 
			
		||||
 | 
			
		||||
PASSED = `grep -s PASS $(PATHR)*.txt`
 | 
			
		||||
FAIL = `grep -s FAIL $(PATHR)*.txt`
 | 
			
		||||
IGNORE = `grep -s IGNORE $(PATHR)*.txt`
 | 
			
		||||
 | 
			
		||||
test: $(BUILD_PATHS) $(RESULTS)
 | 
			
		||||
	@echo "-----------------------\nIGNORES:\n-----------------------"
 | 
			
		||||
	@echo "$(IGNORE)"
 | 
			
		||||
	@echo "-----------------------\nFAILURES:\n-----------------------"
 | 
			
		||||
	@echo "$(FAIL)"
 | 
			
		||||
	@echo "-----------------------\nPASSED:\n-----------------------"
 | 
			
		||||
	@echo "$(PASSED)"
 | 
			
		||||
	@echo "\nDONE"
 | 
			
		||||
 | 
			
		||||
$(PATHR)%.txt: $(PATHB)%.$(TARGET_EXTENSION)
 | 
			
		||||
	-./$< > $@ 2>&1
 | 
			
		||||
 | 
			
		||||
$(PATHB)test_%.$(TARGET_EXTENSION): $(PATHO)test_%.o $(PATHO)tusb_%.o $(PATHU)unity.o #$(PATHD)test%.d
 | 
			
		||||
	$(LINK) -o $@ $^
 | 
			
		||||
 | 
			
		||||
$(PATHO)%.o:: $(PATHT)%.c
 | 
			
		||||
	$(COMPILE) $(CFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(PATHO)%.o:: $(PATHS)common/%.c
 | 
			
		||||
	$(COMPILE) $(CFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(PATHO)%.o:: $(PATHU)%.c $(PATHU)%.h
 | 
			
		||||
	$(COMPILE) $(CFLAGS) $< -o $@
 | 
			
		||||
 | 
			
		||||
$(PATHD)%.d:: $(PATHT)%.c
 | 
			
		||||
	$(DEPEND) $@ $<
 | 
			
		||||
 | 
			
		||||
$(PATHB):
 | 
			
		||||
	$(MKDIR) $(PATHB)
 | 
			
		||||
 | 
			
		||||
$(PATHD):
 | 
			
		||||
	$(MKDIR) $(PATHD)
 | 
			
		||||
 | 
			
		||||
$(PATHO):
 | 
			
		||||
	$(MKDIR) $(PATHO)
 | 
			
		||||
 | 
			
		||||
$(PATHR):
 | 
			
		||||
	$(MKDIR) $(PATHR)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	$(CLEANUP) $(PATHO)*.o
 | 
			
		||||
	$(CLEANUP) $(PATHB)*.$(TARGET_EXTENSION)
 | 
			
		||||
	$(CLEANUP) $(PATHR)*.txt
 | 
			
		||||
 | 
			
		||||
.PRECIOUS: $(PATHB)test%.$(TARGET_EXTENSION)
 | 
			
		||||
.PRECIOUS: $(PATHD)%.d
 | 
			
		||||
.PRECIOUS: $(PATHO)%.o
 | 
			
		||||
.PRECIOUS: $(PATHR)%.txt
 | 
			
		||||
							
								
								
									
										8
									
								
								tests/common/build/results/test_txbuf.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/common/build/results/test_txbuf.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
test/test_txbuf.c:140:test_normal:PASS
 | 
			
		||||
test/test_txbuf.c:141:test_nearly_full:PASS
 | 
			
		||||
test/test_txbuf.c:142:test_wrap_around:PASS
 | 
			
		||||
test/test_txbuf.c:143:test_wrap_around_too_much:PASS
 | 
			
		||||
 | 
			
		||||
-----------------------
 | 
			
		||||
4 Tests 0 Failures 0 Ignored 
 | 
			
		||||
OK
 | 
			
		||||
							
								
								
									
										145
									
								
								tests/common/test/test_txbuf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								tests/common/test/test_txbuf.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*!
 | 
			
		||||
    @file     test_fifo.c
 | 
			
		||||
    @author   Scott Shawcroft
 | 
			
		||||
 | 
			
		||||
    @section LICENSE
 | 
			
		||||
 | 
			
		||||
    Software License Agreement (BSD License)
 | 
			
		||||
 | 
			
		||||
    Copyright (c) 2019, Scott Shawcroft
 | 
			
		||||
    All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
    documentation and/or other materials provided with the distribution.
 | 
			
		||||
    3. Neither the name of the copyright holders nor the
 | 
			
		||||
    names of its contributors may be used to endorse or promote products
 | 
			
		||||
    derived from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
 | 
			
		||||
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
 | 
			
		||||
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
    INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
 | 
			
		||||
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
    This file is part of the tinyusb stack.
 | 
			
		||||
*/
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "unity.h"
 | 
			
		||||
#include "common/tusb_txbuf.h"
 | 
			
		||||
 | 
			
		||||
uint32_t xfer_count = 0;
 | 
			
		||||
uint32_t freshly_transmitted = 0;
 | 
			
		||||
 | 
			
		||||
bool mock_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) {
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT_MESSAGE(0, ((size_t) buffer) % 4, "Transferred buffer not word aligned.");
 | 
			
		||||
    xfer_count++;
 | 
			
		||||
    freshly_transmitted += total_bytes;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tu_txbuf_t txbuf;
 | 
			
		||||
__attribute__((aligned(4))) uint8_t buffer[16];
 | 
			
		||||
 | 
			
		||||
uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
 | 
			
		||||
 | 
			
		||||
void setUp(void) {
 | 
			
		||||
    tu_txbuf_config(&txbuf, buffer, 16, mock_xfer);
 | 
			
		||||
    tu_txbuf_set_ep_addr(&txbuf, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tearDown(void) {
 | 
			
		||||
    xfer_count = 0;
 | 
			
		||||
    freshly_transmitted = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void xfer_callback(void) {
 | 
			
		||||
    uint32_t previously_transmitted = freshly_transmitted;
 | 
			
		||||
    freshly_transmitted = 0;
 | 
			
		||||
 | 
			
		||||
    tu_txbuf_transmit_done_cb(&txbuf, previously_transmitted);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we transfer immediately at the start and that the pointer is rounded to a word.
 | 
			
		||||
void test_normal(void) {
 | 
			
		||||
    uint16_t written = tu_txbuf_write_n(&txbuf, data, 4);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(4, written);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we only accept the data we have room for.
 | 
			
		||||
void test_nearly_full(void) {
 | 
			
		||||
    uint16_t written = tu_txbuf_write_n(&txbuf, data, 11);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(11, written);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
 | 
			
		||||
    written = tu_txbuf_write_n(&txbuf, data, 11);
 | 
			
		||||
    // We only have space for 4 more bytes because 11 + padding are being written.
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(4, written);
 | 
			
		||||
 | 
			
		||||
    // Callback triggers a second write of remaining data.
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(2, xfer_count);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(4, freshly_transmitted);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we only accept the data even when we have to wrap around.
 | 
			
		||||
void test_wrap_around(void) {
 | 
			
		||||
    uint16_t written = tu_txbuf_write_n(&txbuf, data, 11);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(11, written);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
 | 
			
		||||
    written = tu_txbuf_write_n(&txbuf, data, 11);
 | 
			
		||||
    // We can queue all 11 bytes but they are split.
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(11, written);
 | 
			
		||||
    // Four immediately and seven more after the callback.
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(2, xfer_count);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(4, freshly_transmitted);
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(7, freshly_transmitted);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(3, xfer_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that we only accept the data even when we have to wrap around.
 | 
			
		||||
void test_wrap_around_too_much(void) {
 | 
			
		||||
    uint16_t written = tu_txbuf_write_n(&txbuf, data, 11);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(11, written);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(1, xfer_count);
 | 
			
		||||
 | 
			
		||||
    written = tu_txbuf_write_n(&txbuf, data, 17);
 | 
			
		||||
    // We can queue 16 of 17 bytes but they are split.
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(16, written);
 | 
			
		||||
    // Four immediately and 12 more after the callback.
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(2, xfer_count);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(4, freshly_transmitted);
 | 
			
		||||
    xfer_callback();
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(12, freshly_transmitted);
 | 
			
		||||
    TEST_ASSERT_EQUAL_INT(3, xfer_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
UNITY_BEGIN();
 | 
			
		||||
RUN_TEST(test_normal);
 | 
			
		||||
RUN_TEST(test_nearly_full);
 | 
			
		||||
RUN_TEST(test_wrap_around);
 | 
			
		||||
RUN_TEST(test_wrap_around_too_much);
 | 
			
		||||
return UNITY_END();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/vendor/unity
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								tests/vendor/unity
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule tests/vendor/unity added at a284984365
									
								
							
		Reference in New Issue
	
	Block a user