示例#1
0
void cdc_acmd_write(USBD* usbd, CDC_ACMD* cdc_acmd)
{
    if (!cdc_acmd->DTR || !cdc_acmd->tx_idle || cdc_acmd->suspended)
        return;

    unsigned int to_write;
    if (cdc_acmd->tx_size == 0)
        cdc_acmd->tx_size = stream_get_size(cdc_acmd->tx_stream);

    to_write = cdc_acmd->tx_size;
    if (to_write > cdc_acmd->data_ep_size)
        to_write = cdc_acmd->data_ep_size;
    if (to_write)
    {
        cdc_acmd->tx_size -= to_write;
        if (stream_read(cdc_acmd->tx_stream_handle, io_data(cdc_acmd->tx), to_write))
        {
            cdc_acmd->tx_idle = false;
            cdc_acmd->tx->data_size = to_write;
            usbd_usb_ep_write(usbd, cdc_acmd->data_ep, cdc_acmd->tx);
        }
        //just in case of driver failure
        else
            stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE);
    }
    else
        stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE);
}
示例#2
0
void cdc_acmd_class_resume(USBD* usbd, void* param)
{
    CDC_ACMD* cdc_acmd = (CDC_ACMD*)param;
    cdc_acmd->suspended = false;
#if (USBD_CDC_ACM_RX_STREAM_SIZE)
    stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE);
    usbd_usb_ep_read(usbd, cdc_acmd->data_ep, cdc_acmd->rx, cdc_acmd->data_ep_size);
#endif //USBD_CDC_ACM_RX_STREAM_SIZE
}
/* Model output function */
void omni_interface_output(int_T tid)
{
  /* local block i/o variables */
  real_T rtb_HILRead_o3[2];
  real_T rtb_Saturation[3];
  real_T rtb_StreamRead1_o2[3];
  t_stream_ptr rtb_StreamAnswer_o1;
  t_stream_ptr rtb_StreamWrite_o1;
  t_stream_ptr rtb_StreamAnswer1_o1;
  t_stream_ptr rtb_StreamRead1_o1;
  uint8_T rtb_StreamAnswer1_o2;
  boolean_T rtb_LogicalOperator2[2];
  boolean_T rtb_StreamRead1_o4;
  boolean_T rtb_StreamRead1_o3;

  /* S-Function Block: omni_interface/HIL Read (hil_read_block) */
  {
    t_error result = hil_read(omni_interface_DWork.HILInitialize_Card,
      omni_interface_P.HILRead_AnalogChannels, 3U,
      omni_interface_P.HILRead_EncoderChannels, 3U,
      omni_interface_P.HILRead_DigitalChannels, 2U,
      NULL, 0U,
      rtb_Saturation,
      &omni_interface_DWork.HILRead_EncoderBuffer[0],
      &omni_interface_DWork.HILRead_DigitalBuffer[0],
      NULL
      );
    if (result < 0) {
      msg_get_error_messageA(NULL, result, _rt_error_message, sizeof
        (_rt_error_message));
      rtmSetErrorStatus(omni_interface_M, _rt_error_message);
    } else {
      rtb_StreamRead1_o2[0] = omni_interface_DWork.HILRead_EncoderBuffer[0];
      rtb_StreamRead1_o2[1] = omni_interface_DWork.HILRead_EncoderBuffer[1];
      rtb_StreamRead1_o2[2] = omni_interface_DWork.HILRead_EncoderBuffer[2];
      rtb_HILRead_o3[0] = omni_interface_DWork.HILRead_DigitalBuffer[0];
      rtb_HILRead_o3[1] = omni_interface_DWork.HILRead_DigitalBuffer[1];
    }
  }

  /* Gain: '<Root>/Gain2' incorporates:
   *  Bias: '<Root>/Bias3'
   *  Gain: '<Root>/Gain1'
   *  Gain: '<Root>/Gear Ratio'
   */
  omni_interface_B.Gain2[0] = (rtb_StreamRead1_o2[0] +
    omni_interface_P.Bias3_Bias[0]) * omni_interface_P.Gain1_Gain *
    omni_interface_P.GearRatio_Gain[0] * omni_interface_P.Gain2_Gain;
  omni_interface_B.Gain2[1] = (rtb_StreamRead1_o2[1] +
    omni_interface_P.Bias3_Bias[1]) * omni_interface_P.Gain1_Gain *
    omni_interface_P.GearRatio_Gain[1] * omni_interface_P.Gain2_Gain;
  omni_interface_B.Gain2[2] = (rtb_StreamRead1_o2[2] +
    omni_interface_P.Bias3_Bias[2]) * omni_interface_P.Gain1_Gain *
    omni_interface_P.GearRatio_Gain[2] * omni_interface_P.Gain2_Gain;

  /* Switch: '<S8>/Reset' incorporates:
   *  Constant: '<S8>/Initial Condition'
   *  MinMax: '<S2>/MinMax'
   *  UnitDelay: '<S8>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset = omni_interface_P.InitialCondition_Value;
  } else {
    omni_interface_B.Reset = rt_MIN(omni_interface_B.Gain2[0],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE);
  }

  /* Switch: '<S9>/Reset' incorporates:
   *  Constant: '<S9>/Initial Condition'
   *  MinMax: '<S3>/MinMax'
   *  UnitDelay: '<S9>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset_c = omni_interface_P.InitialCondition_Value_d;
  } else {
    omni_interface_B.Reset_c = rt_MIN(omni_interface_B.Gain2[1],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE_i);
  }

  /* Switch: '<S10>/Reset' incorporates:
   *  Constant: '<S10>/Initial Condition'
   *  MinMax: '<S4>/MinMax'
   *  UnitDelay: '<S10>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset_n = omni_interface_P.InitialCondition_Value_g;
  } else {
    omni_interface_B.Reset_n = rt_MIN(omni_interface_B.Gain2[2],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE_a);
  }

  /* Switch: '<S11>/Reset' incorporates:
   *  Constant: '<S11>/Initial Condition'
   *  MinMax: '<S5>/MinMax'
   *  UnitDelay: '<S11>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset_c3 = omni_interface_P.InitialCondition_Value_gd;
  } else {
    omni_interface_B.Reset_c3 = rt_MAX(omni_interface_B.Gain2[0],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE_e);
  }

  /* Switch: '<S12>/Reset' incorporates:
   *  Constant: '<S12>/Initial Condition'
   *  MinMax: '<S6>/MinMax'
   *  UnitDelay: '<S12>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset_l = omni_interface_P.InitialCondition_Value_m;
  } else {
    omni_interface_B.Reset_l = rt_MAX(omni_interface_B.Gain2[1],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE_eh);
  }

  /* Switch: '<S13>/Reset' incorporates:
   *  Constant: '<S13>/Initial Condition'
   *  MinMax: '<S7>/MinMax'
   *  UnitDelay: '<S13>/FixPt Unit Delay1'
   */
  if (0.0 != 0.0) {
    omni_interface_B.Reset_i = omni_interface_P.InitialCondition_Value_f;
  } else {
    omni_interface_B.Reset_i = rt_MAX(omni_interface_B.Gain2[2],
      omni_interface_DWork.FixPtUnitDelay1_DSTATE_d);
  }

  /* S-Function Block: omni_interface/Stream Answer (stream_answer_block) */
  {
    static const t_short endian_test = 0x0201;
    t_error result = 0;
    t_boolean close_listener = (FALSE != 0);
    t_boolean close_client = (FALSE != 0);
    rtb_StreamAnswer_o1 = NULL;
    switch (omni_interface_DWork.StreamAnswer_State) {
     case STREAM_ANSWER_STATE_NOT_LISTENING:
      {
        if (!close_listener) {
          result = stream_listen("tcpip://localhost:18000", true,
            &omni_interface_DWork.StreamAnswer_Listener);
          if (result == 0) {
            omni_interface_DWork.StreamAnswer_State =
              STREAM_ANSWER_STATE_NOT_CONNECTED;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_NOT_CONNECTED:
      {
        if (!close_client) {
          result = stream_accept(omni_interface_DWork.StreamAnswer_Listener,
            omni_interface_P.StreamAnswer_SendBufferSize,
            omni_interface_P.StreamAnswer_ReceiveBufferSize,
            &omni_interface_DWork.StreamAnswer_Client);
          if (result == 0) {
            omni_interface_DWork.StreamAnswer_State =
              STREAM_ANSWER_STATE_CONNECTED;
            stream_set_swap_bytes(omni_interface_DWork.StreamAnswer_Client,
                                  *(t_byte *) &endian_test !=
                                  omni_interface_P.StreamAnswer_Endian);
            rtb_StreamAnswer_o1 = &omni_interface_DWork.StreamAnswer_Client;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_CONNECTED:
      {
        rtb_StreamAnswer_o1 = &omni_interface_DWork.StreamAnswer_Client;
        if (!close_client) {
          break;
        }

        /* Fall through deliberately */
      }

     default:
      {
        t_error close_result = stream_close
          (omni_interface_DWork.StreamAnswer_Client);
        if (close_result == 0) {
          omni_interface_DWork.StreamAnswer_Client = NULL;
          omni_interface_DWork.StreamAnswer_State =
            STREAM_ANSWER_STATE_NOT_CONNECTED;
          rtb_StreamAnswer_o1 = NULL;
          if (close_listener) {
            close_result = stream_close
              (omni_interface_DWork.StreamAnswer_Listener);
            if (close_result == 0) {
              omni_interface_DWork.StreamAnswer_Listener = NULL;
              omni_interface_DWork.StreamAnswer_State =
                STREAM_ANSWER_STATE_NOT_LISTENING;
            } else if (result == 0) {
              result = close_result;
            }
          }
        } else if (result == 0) {
          result = close_result;
        }
        break;
      }
    }

    rtb_StreamAnswer1_o2 = omni_interface_DWork.StreamAnswer_State;
    omni_interface_B.StreamAnswer_o3 = (int32_T) result;
  }

  /* Logic: '<Root>/Logical Operator' incorporates:
   *  Logic: '<Root>/Logical Operator1'
   *  RelationalOperator: '<S1>/Compare'
   */
  omni_interface_B.LogicalOperator = ((rtb_StreamAnswer1_o2 != 0U) &&
    (!((omni_interface_B.StreamAnswer_o3 != 0) != 0U)));

  /* S-Function (stream_write_block): '<Root>/Stream Write' */
  {
    t_error result;
    if (rtb_StreamAnswer_o1 != NULL) {
      result = stream_send_unit_array(*rtb_StreamAnswer_o1,
        omni_interface_B.Gain2, sizeof(real_T), 3);
      if (result == 1) {
        stream_flush(*rtb_StreamAnswer_o1);
      }

      if (result == -QERR_WOULD_BLOCK) {
        result = 0;
      }
    }

    rtb_StreamWrite_o1 = rtb_StreamAnswer_o1;
  }

  /* S-Function (stream_read_block): '<Root>/Stream Read' */
  /* S-Function Block: omni_interface/Stream Read (stream_read_block) */
  {
    t_error result;
    if (rtb_StreamWrite_o1 != NULL) {
      result = stream_receive_unit_array(*rtb_StreamWrite_o1,
        omni_interface_B.StreamRead_o2, sizeof(real_T), 3);
      omni_interface_B.StreamRead_o3 = (result > 0);
      if (result == -QERR_WOULD_BLOCK) {
        result = 0;
      }

      /*
         if (result <= 0 && result != -QERR_WOULD_BLOCK) {
         memset(omni_interface_B.StreamRead_o2, 0, 3 * sizeof(real_T));
         }
       */
    } else {
      memset(omni_interface_B.StreamRead_o2, 0, 3 * sizeof(real_T));
      omni_interface_B.StreamRead_o3 = false;
      result = 0;
    }

    rtb_StreamRead1_o1 = rtb_StreamWrite_o1;
  }

  /* S-Function Block: omni_interface/Stream Answer1 (stream_answer_block) */
  {
    static const t_short endian_test = 0x0201;
    t_error result = 0;
    t_boolean close_listener = (FALSE != 0);
    t_boolean close_client = (FALSE != 0);
    rtb_StreamAnswer1_o1 = NULL;
    switch (omni_interface_DWork.StreamAnswer1_State) {
     case STREAM_ANSWER_STATE_NOT_LISTENING:
      {
        if (!close_listener) {
          result = stream_listen("tcpip://localhost:18002", true,
            &omni_interface_DWork.StreamAnswer1_Listener);
          if (result == 0) {
            omni_interface_DWork.StreamAnswer1_State =
              STREAM_ANSWER_STATE_NOT_CONNECTED;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_NOT_CONNECTED:
      {
        if (!close_client) {
          result = stream_accept(omni_interface_DWork.StreamAnswer1_Listener,
            omni_interface_P.StreamAnswer1_SendBufferSize,
            omni_interface_P.StreamAnswer1_ReceiveBufferSize,
            &omni_interface_DWork.StreamAnswer1_Client);
          if (result == 0) {
            omni_interface_DWork.StreamAnswer1_State =
              STREAM_ANSWER_STATE_CONNECTED;
            stream_set_swap_bytes(omni_interface_DWork.StreamAnswer1_Client,
                                  *(t_byte *) &endian_test !=
                                  omni_interface_P.StreamAnswer1_Endian);
            rtb_StreamAnswer1_o1 = &omni_interface_DWork.StreamAnswer1_Client;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_CONNECTED:
      {
        rtb_StreamAnswer1_o1 = &omni_interface_DWork.StreamAnswer1_Client;
        if (!close_client) {
          break;
        }

        /* Fall through deliberately */
      }

     default:
      {
        t_error close_result = stream_close
          (omni_interface_DWork.StreamAnswer1_Client);
        if (close_result == 0) {
          omni_interface_DWork.StreamAnswer1_Client = NULL;
          omni_interface_DWork.StreamAnswer1_State =
            STREAM_ANSWER_STATE_NOT_CONNECTED;
          rtb_StreamAnswer1_o1 = NULL;
          if (close_listener) {
            close_result = stream_close
              (omni_interface_DWork.StreamAnswer1_Listener);
            if (close_result == 0) {
              omni_interface_DWork.StreamAnswer1_Listener = NULL;
              omni_interface_DWork.StreamAnswer1_State =
                STREAM_ANSWER_STATE_NOT_LISTENING;
            } else if (result == 0) {
              result = close_result;
            }
          }
        } else if (result == 0) {
          result = close_result;
        }
        break;
      }
    }

    omni_interface_B.StreamAnswer1_o3 = (int32_T) result;
  }

  /* Gain: '<Root>/Gain' */
  rtb_StreamRead1_o2[0] = omni_interface_P.Gain_Gain[0] *
    omni_interface_B.StreamRead_o2[0];
  rtb_StreamRead1_o2[1] = omni_interface_P.Gain_Gain[1] *
    omni_interface_B.StreamRead_o2[1];
  rtb_StreamRead1_o2[2] = omni_interface_P.Gain_Gain[2] *
    omni_interface_B.StreamRead_o2[2];

  /* Product: '<Root>/Product' */
  rtb_Saturation[0] = (int32_T)omni_interface_B.LogicalOperator ?
    rtb_StreamRead1_o2[0] : 0.0;
  rtb_Saturation[1] = (int32_T)omni_interface_B.LogicalOperator ?
    rtb_StreamRead1_o2[1] : 0.0;
  rtb_Saturation[2] = (int32_T)omni_interface_B.LogicalOperator ?
    rtb_StreamRead1_o2[2] : 0.0;

  /* Saturate: '<Root>/Saturation' */
  rtb_Saturation[0] = rt_SATURATE(rtb_Saturation[0],
    omni_interface_P.Saturation_LowerSat, omni_interface_P.Saturation_UpperSat);
  rtb_Saturation[1] = rt_SATURATE(rtb_Saturation[1],
    omni_interface_P.Saturation_LowerSat, omni_interface_P.Saturation_UpperSat);
  rtb_Saturation[2] = rt_SATURATE(rtb_Saturation[2],
    omni_interface_P.Saturation_LowerSat, omni_interface_P.Saturation_UpperSat);

  /* S-Function Block: omni_interface/HIL Write (hil_write_block) */
  {
    t_error result;
    result = hil_write(omni_interface_DWork.HILInitialize_Card,
                       NULL, 0U,
                       omni_interface_P.HILWrite_PWMChannels, 3U,
                       NULL, 0U,
                       NULL, 0U,
                       NULL,
                       rtb_Saturation,
                       NULL,
                       NULL
                       );
    if (result < 0) {
      msg_get_error_messageA(NULL, result, _rt_error_message, sizeof
        (_rt_error_message));
      rtmSetErrorStatus(omni_interface_M, _rt_error_message);
    }
  }

  /* S-Function (stream_read_block): '<Root>/Stream Read1' */
  /* S-Function Block: omni_interface/Stream Read1 (stream_read_block) */
  {
    t_error result;
    if (rtb_StreamAnswer1_o1 != NULL) {
      result = stream_receive_unit_array(*rtb_StreamAnswer1_o1,
        rtb_StreamRead1_o2, sizeof(real_T), 3);
      if (result == -QERR_WOULD_BLOCK) {
        result = 0;
      }

      /*
         if (result <= 0 && result != -QERR_WOULD_BLOCK) {
         memset(rtb_StreamRead1_o2, 0, 3 * sizeof(real_T));
         }
       */
    } else {
      memset(rtb_StreamRead1_o2, 0, 3 * sizeof(real_T));
      result = 0;
    }

    rtb_StreamRead1_o1 = rtb_StreamAnswer1_o1;
  }

  /* Logic: '<Root>/Logical Operator2' */
  rtb_LogicalOperator2[0] = ((rtb_HILRead_o3[0] != 0.0) || (0.0 != 0.0) ||
    (rtb_StreamRead1_o2[1] != 0.0));
  rtb_LogicalOperator2[1] = ((rtb_HILRead_o3[1] != 0.0) || (0.0 != 0.0) ||
    (rtb_StreamRead1_o2[1] != 0.0));

  /* Stop: '<Root>/Stop Simulation' */
  if (rtb_LogicalOperator2[0] || rtb_LogicalOperator2[1]) {
    rtmSetStopRequested(omni_interface_M, 1);
  }

  UNUSED_PARAMETER(tid);
}
示例#4
0
/* Model output function */
void Server_output(int_T tid)
{
  /* local block i/o variables */
  t_stream_ptr rtb_StreamAnswer_o1;
  t_stream_ptr rtb_StreamWrite_o1;

  /* S-Function Block: Server/Stream Answer (stream_answer_block) */
  {
    static const t_short endian_test = 0x0201;
    t_error result = 0;
    t_boolean close_listener = (FALSE != 0);
    t_boolean close_client = (FALSE != 0);
    rtb_StreamAnswer_o1 = NULL;
    switch (Server_DWork.StreamAnswer_State) {
     case STREAM_ANSWER_STATE_NOT_LISTENING:
      {
        if (!close_listener) {
          result = stream_listen("tcpip://localhost:18000", true,
            &Server_DWork.StreamAnswer_Listener);
          if (result == 0) {
            Server_DWork.StreamAnswer_State = STREAM_ANSWER_STATE_NOT_CONNECTED;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_NOT_CONNECTED:
      {
        if (!close_client) {
          result = stream_accept(Server_DWork.StreamAnswer_Listener,
            Server_P.StreamAnswer_SendBufferSize,
            Server_P.StreamAnswer_ReceiveBufferSize,
            &Server_DWork.StreamAnswer_Client);
          if (result == 0) {
            Server_DWork.StreamAnswer_State = STREAM_ANSWER_STATE_CONNECTED;
            stream_set_swap_bytes(Server_DWork.StreamAnswer_Client, *(t_byte *)
                                  &endian_test != Server_P.StreamAnswer_Endian);
            rtb_StreamAnswer_o1 = &Server_DWork.StreamAnswer_Client;
          }
        }
        break;
      }

     case STREAM_ANSWER_STATE_CONNECTED:
      {
        rtb_StreamAnswer_o1 = &Server_DWork.StreamAnswer_Client;
        if (!close_client) {
          break;
        }

        /* Fall through deliberately */
      }

     default:
      {
        t_error close_result = stream_close(Server_DWork.StreamAnswer_Client);
        if (close_result == 0) {
          Server_DWork.StreamAnswer_Client = NULL;
          Server_DWork.StreamAnswer_State = STREAM_ANSWER_STATE_NOT_CONNECTED;
          rtb_StreamAnswer_o1 = NULL;
          if (close_listener) {
            close_result = stream_close(Server_DWork.StreamAnswer_Listener);
            if (close_result == 0) {
              Server_DWork.StreamAnswer_Listener = NULL;
              Server_DWork.StreamAnswer_State =
                STREAM_ANSWER_STATE_NOT_LISTENING;
            } else if (result == 0) {
              result = close_result;
            }
          }
        } else if (result == 0) {
          result = close_result;
        }
        break;
      }
    }

    Server_B.StreamAnswer_o2 = Server_DWork.StreamAnswer_State;
  }

  /* Sin: '<Root>/Sine Wave' */
  Server_B.SineWave = sin(Server_P.SineWave_Freq * Server_M->Timing.t[0] +
    Server_P.SineWave_Phase) * Server_P.SineWave_Amp + Server_P.SineWave_Bias;

  /* S-Function (stream_write_block): '<Root>/Stream Write' */
  {
    t_error result;
    if (rtb_StreamAnswer_o1 != NULL) {
      result = stream_send_unit_array(*rtb_StreamAnswer_o1, &Server_B.SineWave,
        sizeof(real_T), 1);
      if (result == 1) {
        stream_flush(*rtb_StreamAnswer_o1);
      }

      if (result == -QERR_WOULD_BLOCK) {
        result = 0;
      }
    }

    rtb_StreamWrite_o1 = rtb_StreamAnswer_o1;
  }

  UNUSED_PARAMETER(tid);
}
示例#5
0
void cdc_acmd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg)
{
    USB_INTERFACE_DESCRIPTOR* iface;
    USB_INTERFACE_DESCRIPTOR* diface;
    CDC_UNION_DESCRIPTOR* u;
    USB_ENDPOINT_DESCRIPTOR* ep;
    uint8_t data_ep, data_iface;
    uint16_t data_ep_size;
    uint8_t control_ep, control_iface;
    uint16_t control_ep_size;

    //check control/data ep here
    for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface))
    {
        //also skip RNDIS
        if ((iface->bInterfaceClass != CDC_COMM_INTERFACE_CLASS) || (iface->bInterfaceSubClass != CDC_ACM) || (iface->bInterfaceProtocol == CDC_CP_VENDOR))
            continue;
#if (USBD_CDC_ACM_DEBUG)
        printf("Found USB CDC ACM interface: %d\n", iface->bInterfaceNumber);
#endif //USBD_CDC_ACM_DEBUG
        //find union descriptor
        for (u = usb_interface_get_first_descriptor(cfg, iface, CS_INTERFACE); u != NULL; u = usb_interface_get_next_descriptor(cfg, u, CS_INTERFACE))
        {
            if ((u->bDescriptorSybType == CDC_DESCRIPTOR_UNION) && (u->bControlInterface == iface->bInterfaceNumber) &&
                (u->bFunctionLength > sizeof(CDC_UNION_DESCRIPTOR)))
                break;
        }
        if (u == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning - no UNION descriptor, skipping interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
        data_iface = ((uint8_t*)u)[sizeof(CDC_UNION_DESCRIPTOR)];
        diface = usb_find_interface(cfg, data_iface);
        if (diface == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning no data interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
#if (USBD_CDC_ACM_DEBUG)
        printf("Found USB CDC ACM data interface: %d\n", data_iface);
#endif //USBD_CDC_ACM_DEBUG

        ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, diface, USB_ENDPOINT_DESCRIPTOR_TYPE);
        if (ep == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning no data EP, skipping interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
        data_ep = USB_EP_NUM(ep->bEndpointAddress);
        data_ep_size = ep->wMaxPacketSize;

        control_iface = iface->bInterfaceNumber;
        control_ep = control_ep_size = 0;
        ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE);
        if (ep != NULL)
        {
            control_ep = USB_EP_NUM(ep->bEndpointAddress);
            control_ep_size = ep->wMaxPacketSize;
        }

        //configuration is ok, applying
        CDC_ACMD* cdc_acmd = (CDC_ACMD*)malloc(sizeof(CDC_ACMD));
        if (cdc_acmd == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            return;
        }

        cdc_acmd->data_iface = data_iface;
        cdc_acmd->data_ep = data_ep;
        cdc_acmd->data_ep_size = data_ep_size;
        cdc_acmd->tx = cdc_acmd->rx = NULL;
        cdc_acmd->tx_stream = cdc_acmd->rx_stream = cdc_acmd->tx_stream_handle = cdc_acmd->rx_stream_handle = INVALID_HANDLE;
        cdc_acmd->suspended = false;

        cdc_acmd->control_iface = control_iface;
        cdc_acmd->control_ep = control_ep;
        cdc_acmd->control_ep_size = control_ep_size;
        cdc_acmd->notify = NULL;
        cdc_acmd->notify_busy = cdc_acmd->notify_pending = false;
#if (USBD_CDC_ACM_FLOW_CONTROL)
        cdc_acmd->flow_sending = false;
        cdc_acmd->flow_changed = false;
        cdc_acmd->break_count = 0;
#endif //USBD_CDC_ACM_FLOW_CONTROL

#if (USBD_CDC_ACM_TX_STREAM_SIZE)
        cdc_acmd->tx = io_create(cdc_acmd->data_ep_size);
        cdc_acmd->tx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE);
        cdc_acmd->tx_stream_handle = stream_open(cdc_acmd->tx_stream);
        if (cdc_acmd->tx == NULL || cdc_acmd->tx_stream_handle == INVALID_HANDLE)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            cdc_acmd_destroy(cdc_acmd);
            return;
        }
        cdc_acmd->tx_size = 0;
        cdc_acmd->tx_idle = true;
        usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size);
        stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE);
#endif //USBD_CDC_ACM_TX_STREAM_SIZE

#if (USBD_CDC_ACM_RX_STREAM_SIZE)
        cdc_acmd->rx = io_create(cdc_acmd->data_ep_size);
        cdc_acmd->rx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE);
        cdc_acmd->rx_stream_handle = stream_open(cdc_acmd->rx_stream);
        if (cdc_acmd->rx == NULL || cdc_acmd->rx_stream_handle == INVALID_HANDLE)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            cdc_acmd_destroy(cdc_acmd);
            return;
        }
        cdc_acmd->rx_free = 0;
        usbd_usb_ep_open(usbd, cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size);
        usbd_usb_ep_read(usbd, cdc_acmd->data_ep, cdc_acmd->rx, cdc_acmd->data_ep_size);
#endif //USBD_CDC_ACM_RX_STREAM_SIZE

        usbd_register_interface(usbd, cdc_acmd->data_iface, &__CDC_ACMD_CLASS, cdc_acmd);
        usbd_register_endpoint(usbd, cdc_acmd->data_iface, cdc_acmd->data_ep);

        if (control_ep_size)
        {
            if (cdc_acmd->control_ep_size < 16)
            {
#if (USBD_CDC_ACM_DEBUG)
                printf("USB CDC ACM: Warning - control endpoint is too small(%d), 16 at least required to fit notify", cdc_acmd->control_ep_size);
#endif //USBD_CDC_ACM_DEBUG
                cdc_acmd->notify = io_create(16);
            }
            else
                cdc_acmd->notify = io_create(cdc_acmd->control_ep_size);
            if (cdc_acmd->notify == NULL)
            {
                cdc_acmd_destroy(cdc_acmd);
                return;
            }
            usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->control_ep, USB_EP_INTERRUPT, cdc_acmd->control_ep_size);
            usbd_register_interface(usbd, cdc_acmd->control_iface, &__CDC_ACMD_CLASS, cdc_acmd);
            usbd_register_endpoint(usbd, cdc_acmd->control_iface, cdc_acmd->control_ep);
            cdc_acmd_notify_serial_state(usbd, cdc_acmd, CDC_SERIAL_STATE_DCD | CDC_SERIAL_STATE_DSR);
        }
        cdc_acmd->DTR = cdc_acmd->RTS = false;
        cdc_acmd->baud.baud = 115200;
        cdc_acmd->baud.data_bits = 8;
        cdc_acmd->baud.parity = 'N';
        cdc_acmd->baud.stop_bits = 1;
    }
}