USB_STATUS usb_class_cdc_bind_data_interfaces
   (
      /* [IN] pointer to device instance */
      _usb_device_instance_handle      dev_handle,

      CLASS_CALL_STRUCT_PTR            ccs_ptr
   ) 
{
    USB_CDC_DESC_UNION_PTR            union_desc;
    INTERFACE_DESCRIPTOR_PTR          if_desc;
    int_32 i, j;
 
    union_desc = ((USB_ACM_CLASS_INTF_STRUCT_PTR) ccs_ptr->class_intf_handle)->union_desc;

    /* Now link all already initialized interfaces
        that should be controlled by this ACM */
    for (i = 0; ; i++) {
        if (USB_OK != _usb_hostdev_get_descriptor(
            dev_handle,
            NULL,
            USB_DESC_TYPE_IF,  /* search for all interfaces */
            i,                 /* Index of descriptor */
            0,                 /* Index of interface alternate */
            &if_desc))
                break;
        for (j = 0; j < union_desc->bFunctionLength - 3; j++)
            if (if_desc->bInterfaceNumber == union_desc->bSlaveInterface[j]) {
                /* the found (data) interface if_desc should be controlled by this ACM */
                usb_class_cdc_bind_data_interface((pointer2)ccs_ptr, if_desc);
                break;
            }
    }
    /* Store control interface for data interfaces included later */
    usb_class_cdc_register_interface(ccs_ptr, &ctrl_anchor);
    
    return USB_OK;
}
Esempio n. 2
0
static void usb_host_mass_test_storage
   (
      void
   )
{ /* Body */
   USB_STATUS                                 status = USB_OK;
   uint_8                                     bLun = 0;
   INQUIRY_DATA_FORMAT                        inquiry;
   CAPACITY_LIST                              capacity_list;
   #if 0
   MODE_SELECT_PARAMETER_LIST                 md_list;
   #endif
   MASS_STORAGE_READ_CAPACITY_CMD_STRUCT_INFO read_capacity;
   REQ_SENSE_DATA_FORMAT                      req_sense;
   FORMAT_UNIT_PARAMETER_BLOCK                formatunit = { 0};
   _mqx_int                                   block_len;
   DEVICE_DESCRIPTOR_PTR                      pdd;
   CBW_STRUCT_PTR cbw_ptr = pCmd->CBW_PTR;
   CSW_STRUCT_PTR csw_ptr = pCmd->CSW_PTR;

   USB_mem_zero(buff_out,0x0F);
   USB_mem_zero(buff_in,0x400C);
   USB_mem_zero(pCmd->CSW_PTR,sizeof(CSW_STRUCT));
   USB_mem_zero(pCmd->CBW_PTR,sizeof(CBW_STRUCT));
   USB_mem_zero(pCmd,sizeof(COMMAND_OBJECT_STRUCT));
   
   pCmd->CBW_PTR  = cbw_ptr;
   pCmd->CSW_PTR  = csw_ptr;
   pCmd->LUN      = bLun;
   pCmd->CALL_PTR = (pointer)&mass_device.class_intf;
   pCmd->CALLBACK = usb_host_mass_bulk_callback;

   printf("\n =============START OF A NEW SESSION==================");

   if (USB_OK != _usb_hostdev_get_descriptor(
      mass_device.dev_handle,
      NULL,
      USB_DESC_TYPE_DEV,
      0,
      0,
      (pointer *) &pdd))
   {
      printf ("\nCould not retrieve device descriptor.");
      return;
   }
   else
      printf("\nVID = 0x%04x, PID = 0x%04x", SHORT_LE_TO_HOST(*(uint_16*)pdd->idVendor), SHORT_LE_TO_HOST(*(uint_16*)pdd->idProduct));

   /* Test the GET MAX LUN command */
   printf("\nTesting: GET MAX LUN Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_class_mass_getmaxlun_bulkonly(
      (pointer)&mass_device.class_intf, &bLun,
      usb_host_mass_ctrl_callback);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack) {;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   /* Test the TEST UNIT READY command */
   printf("Testing: TEST UNIT READY Command");
   fflush(stdout);

   bCallBack = FALSE;

   status =  usb_mass_ufi_test_unit_ready(pCmd);
   
   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   /* Test the INQUIRY command */
   printf("Testing: INQUIRY Command");
   fflush(stdout);

   bCallBack = FALSE;

   status = usb_mass_ufi_inquiry(pCmd, (uchar_ptr) &inquiry,
      sizeof(INQUIRY_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the READ FORMAT CAPACITY command */
   printf("Testing: READ FORMAT CAPACITIES Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_format_capacity(pCmd, (uchar_ptr)&capacity_list,
      sizeof(CAPACITY_LIST));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the READ CAPACITY command */
   printf("Testing: READ CAPACITY Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_read_capacity(pCmd, (uchar_ptr)&read_capacity,
      sizeof(MASS_STORAGE_READ_CAPACITY_CMD_STRUCT_INFO));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   block_len = HOST_TO_BE_LONG(* (uint_32 *) &read_capacity.BLENGTH);

#if 0
   /* Test the MODE SELECT command */
   printf("Testing: MODE SELECT Command");
   fflush(stdout);
   bCallBack = FALSE;

   //md_list. Fill parameters here
   USB_mem_zero (&md_list, sizeof (MODE_SELECT_PARAMETER_LIST));
   md_list.MODE_PARAM_HEADER.BLENGTH[1] = 0x06;
   
   status = usb_mass_ufi_mode_select(pCmd, &md_list, 8);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
#endif

   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the READ(10) command */
   printf("Testing: READ(10) Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_read_10(pCmd, 0, buff_in, block_len, 1);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the MODE SENSE command */
   printf("Testing: MODE SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_mode_sense(pCmd,
      2, //PC
      0x3F, //page code
      buff_in,
      (uint_32)0x08);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the PREVENT ALLOW command */
   printf("Testing: PREVENT-ALLOW MEDIUM REMOVAL Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_prevent_allow_medium_removal(
      pCmd,
      1 // prevent
      );

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the VERIFY command */
   printf("Testing: VERIFY Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_verify(
      pCmd,
      0x400, // block address
      1 //length to be verified
      );

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }
   
   /* Test the WRITE(10) command */
   printf("Testing: WRITE(10) Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_write_10(pCmd, 8, buff_out, block_len, 1);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   /* Test the REQUEST SENSE command */
   printf("Testing: REQUEST SENSE Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_request_sense(pCmd, &req_sense,
      sizeof(REQ_SENSE_DATA_FORMAT));

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   /* Test the START-STOP UNIT command */
   printf("Testing: START-STOP UNIT Command");
   fflush(stdout);
   bCallBack = FALSE;

   status = usb_mass_ufi_start_stop(pCmd, 0, 1);

   if ((status != USB_OK) && (status != USB_STATUS_TRANSFER_QUEUED))
   {
      printf ("\n...ERROR");
      return;
   }
   else
   {
      /* Wait till command comes back */
      while (!bCallBack){;}
      if (!bStatus) {
         printf("...OK\n");
      }
      else {
         printf("...Unsupported by device (bStatus=0x%x)\n", bStatus);
      }
   }

   printf("\nTest done!");
   fflush(stdout);
} /* Endbody */
Esempio n. 3
0
USB_STATUS usb_class_audio_stream_get_descriptors
(
    /* [IN] pointer to device instance */
    _usb_device_instance_handle      dev_handle,

    /* [IN] pointer to interface descriptor */
    _usb_interface_descriptor_handle intf_handle,

    /* [OUT] pointer to specific audio stream interface descriptor */
    USB_AUDIO_STREAM_DESC_SPEPIFIC_AS_IF_PTR _PTR_       as_itf_desc,

    /* [OUT] pointer to format type descriptor */
    USB_AUDIO_STREAM_DESC_FORMAT_TYPE_PTR _PTR_        	 frm_type_desc,

    /* [OUT] pointer to specific isochronous endpoint descriptor */
    USB_AUDIO_STREAM_DESC_SPECIFIC_ISO_ENDP_PTR _PTR_		iso_endp_spec_desc
)
{
    INTERFACE_DESCRIPTOR_PTR   intf_ptr =
        (INTERFACE_DESCRIPTOR_PTR)intf_handle;
    USB_STATUS                 status;
    _mqx_int i;
    USB_AUDIO_STREAM_FUNC_DESC_PTR      fd;

#ifdef _HOST_DEBUG_
    DEBUG_LOG_TRACE("usb_class_audio_stream_get_descriptors");
#endif

    status = USB_OK;
    /* collect all interface functional descriptors */
    for (i = 0; ; i++) {
        if (USB_OK != _usb_hostdev_get_descriptor(
                    dev_handle,
                    intf_handle,
                    USB_DESC_TYPE_CS_INTERFACE,  /* Functional descriptor for interface */
                    i,                           /* Index of descriptor */
                    intf_ptr->bAlternateSetting, /* Index of interface alternate */
                    (pointer _PTR_) &fd))
        {
            /* Here we can check capabilities from functional descriptors */
            /* But for now, nothing is checked */
            if (as_itf_desc == NULL)
                status = USBERR_INIT_FAILED;
            break;
        }
        /* Check if this union descriptor describes master for this interface */
        switch (fd->as_general.bDescriptorSubtype) {
        case USB_DESC_SUBTYPE_AS_CS_GENERAL:
            *as_itf_desc = &fd->as_general;
            break;
        case USB_DESC_SUBTYPE_AS_CS_FORMAT_TYPE:
            *frm_type_desc = &fd->frm_type;
            break;
        }
        if (status != USB_OK)
            break;
    }

    /* collect all interface functional descriptors */
    for (i = 0; ; i++) {
        if (USB_OK != _usb_hostdev_get_descriptor(
                    dev_handle,
                    intf_handle,
                    USB_DESC_TYPE_CS_ENDPOINT,  /* Functional descriptor for interface */
                    i,                           /* Index of descriptor */
                    intf_ptr->bAlternateSetting, /* Index of interface alternate */
                    (pointer _PTR_) &fd))
        {
            /* Here we can check capabilities from functional descriptors */
            /* But for now, nothing is checked */
            if (as_itf_desc == NULL)
                status = USBERR_INIT_FAILED;
            break;
        }
        /* Check if this union descriptor describes master for this interface */
        switch (fd->as_general.bDescriptorSubtype) {
        case USB_DESC_CLASS_ENDPOINT_GENERAL:
            *iso_endp_spec_desc = &fd->iso_endp_specific;
            break;
        default:
            break;
        }
        if (status != USB_OK)
            break;
    }

#ifdef _HOST_DEBUG_
    if (!status)
        DEBUG_LOG_TRACE("usb_class_audio_stream_get_descriptors, SUCCESSFULL");
    else
        DEBUG_LOG_TRACE("usb_class_audio_stream_get_descriptors, FAILED");
#endif

    return status;
}
Esempio n. 4
0
/*FUNCTION*----------------------------------------------------------------
*
* Function Name  : usb_class_audio_control_get_descriptors
* Returned Value : USB_OK
* Comments       :
*     This function is hunting for descriptors in the device configuration
*     and fills back fields if the descriptor was found.
*     Must be run in locked state and validated USB device or
*     directly from attach event.
*END*--------------------------------------------------------------------*/
USB_STATUS usb_class_audio_control_get_descriptors
(
    /* [IN] pointer to device instance */
    _usb_device_instance_handle      			dev_handle,

    /* [IN] pointer to interface descriptor */
    _usb_interface_descriptor_handle 			intf_handle,

    /* [OUT] pointer to header descriptor */
    USB_AUDIO_CTRL_DESC_HEADER_PTR _PTR_        header_desc,

    /* [OUT] pointer to input terminal descriptor */
    USB_AUDIO_CTRL_DESC_IT_PTR _PTR_        	it_desc,

    /* [OUT] pointer to output terminal descriptor */
    USB_AUDIO_CTRL_DESC_OT_PTR _PTR_        	ot_desc,

    /* [OUT] pointer to feature unit descriptor */
    USB_AUDIO_CTRL_DESC_FU_PTR _PTR_     		fu_desc
)
{
    INTERFACE_DESCRIPTOR_PTR   intf_ptr = (INTERFACE_DESCRIPTOR_PTR)intf_handle;
    USB_STATUS                 status;
    int_32 i;
    USB_AUDIO_CTRL_FUNC_DESC_PTR      fd;

#ifdef _HOST_DEBUG_
    DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors");
#endif

    status = USB_OK;
    /* collect all interface functional descriptors */
    for (i = 0; ; i++) {
        if (USB_OK != _usb_hostdev_get_descriptor(
                    dev_handle,
                    intf_handle,
                    USB_DESC_TYPE_CS_INTERFACE,  /* Functional descriptor for interface */
                    i,                           /* Index of descriptor */
                    intf_ptr->bAlternateSetting, /* Index of interface alternate */
                    (pointer _PTR_) &fd))
        {
            /* Here we can check capabilities from functional descriptors */
            /* But for now, nothing is checked */
            if (fu_desc == NULL)
                status = USBERR_INIT_FAILED;
            break;
        }
        /* Check if this union descriptor describes master for this interface */
        switch (fd->header.bDescriptorSubtype) {
        case USB_DESC_SUBTYPE_AUDIO_CS_HEADER:
            *header_desc = &fd->header;
            if (SHORT_LE_TO_HOST(*(uint_16*)((*header_desc)->bcdCDC)) > 0x0110)
                status = USBERR_INIT_FAILED;
            break;
        case USB_DESC_SUBTYPE_AUDIO_CS_IT:
            *it_desc = &fd->it;
            break;
        case USB_DESC_SUBTYPE_AUDIO_CS_OT:
            *ot_desc = &fd->ot;
            break;
        case USB_DESC_SUBTYPE_AUDIO_CS_FU:
            *fu_desc = &fd->fu;
            break;
        }
        if (status != USB_OK)
            break;
    }

#ifdef _HOST_DEBUG_
    if (!status)
        DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors, SUCCESSFULL");
    else
        DEBUG_LOG_TRACE("usb_class_audio_control_get_descriptors, FAILED");
#endif

    return status;
}
USB_STATUS usb_class_cdc_get_ctrl_descriptor
    (
      /* [IN] pointer to device instance */
      _usb_device_instance_handle      dev_handle,

      /* [IN] pointer to interface descriptor */
      _usb_interface_descriptor_handle intf_handle,
      
      INTERFACE_DESCRIPTOR_PTR _PTR_   if_desc_ptr
    )
{
    USB_CDC_FUNC_DESC_PTR      fd_desc;
    INTERFACE_DESCRIPTOR_PTR   if_desc;
    INTERFACE_DESCRIPTOR_PTR   intf_ptr =
       (INTERFACE_DESCRIPTOR_PTR)intf_handle;
    USB_STATUS                 status;
    int_32 i, j, k;
    int_32 ctrl_intf = -1; /* assume not found */

    status = USBERR_INIT_FAILED; 
    *if_desc_ptr = NULL; /* presume not found */

    /* Find union descriptor containing this data descriptor */
    for (i = 0; ; i++) {
        if (USB_OK == _usb_hostdev_get_descriptor(
            dev_handle,
            NULL,
            USB_DESC_TYPE_CS_INTERFACE,  /* Get any functional descriptor */
            i,                           /* Index of descriptor */
            intf_ptr->bAlternateSetting, /* Index of interface alternate */
            &fd_desc))
        {
            if (fd_desc->header.bDescriptorSubtype != USB_DESC_SUBTYPE_CS_UNION)
                continue;
            /* Here we get only when union descriptor found */
            /* Find if there is this data interface in the found union descriptor */
            for (j = 0; j < fd_desc->uni.bFunctionLength - 3; j++) {
                if (intf_ptr->bInterfaceNumber == fd_desc->uni.bSlaveInterface[j]) {
                    /* Union descriptor containing our data interface found */
                    ctrl_intf = fd_desc->uni.bMasterInterface; /* copy control interface number */
                    break;
                }
            }
            if (ctrl_intf != -1) /* when control interface was already found */
                break; /* finish any next search for union descriptors */
        }
        else
            break;
    }
    
    if (ctrl_intf != -1) {
        /* find interface descriptor from control interface number */
        for (i = 0; ; i++) {
            if (USB_OK == _usb_hostdev_get_descriptor(
                dev_handle,
                NULL,                        /* Search within device scope */
                USB_DESC_TYPE_IF,            /* Get any interface descriptor */
                i,                           /* Index of descriptor */
                intf_ptr->bAlternateSetting, /* Index of interface alternate */
                &if_desc))
            {
                if (if_desc->bInterfaceNumber == ctrl_intf) {
                    /* Interface descriptor of control interface found */
                    *if_desc_ptr = if_desc;
                    status = USB_OK;
                    break;
                }
            }
        }
    }

    return status;
}
USB_STATUS usb_class_cdc_get_acm_descriptors
(
      /* [IN] pointer to device instance */
      _usb_device_instance_handle      dev_handle,

      /* [IN] pointer to interface descriptor */
      _usb_interface_descriptor_handle intf_handle,

      USB_CDC_DESC_ACM_PTR _PTR_       acm_desc,
      USB_CDC_DESC_CM_PTR _PTR_        cm_desc,
      USB_CDC_DESC_HEADER_PTR _PTR_    header_desc,
      USB_CDC_DESC_UNION_PTR _PTR_     union_desc
) 
{
    INTERFACE_DESCRIPTOR_PTR   intf_ptr =
        (INTERFACE_DESCRIPTOR_PTR)intf_handle;
    USB_STATUS                 status;
    int_32 i;
    USB_CDC_FUNC_DESC_PTR      fd;
    INTERFACE_DESCRIPTOR_PTR   if_desc;

    status = USB_OK;
    /* collect all interface functional descriptors */
    for (i = 0; ; i++) {
        if (USB_OK != _usb_hostdev_get_descriptor(
            dev_handle,
            intf_handle,
            USB_DESC_TYPE_CS_INTERFACE,  /* Functional descriptor for interface */
            i,                           /* Index of descriptor */
            intf_ptr->bAlternateSetting, /* Index of interface alternate */
            &fd))
        {
            /* Here we can check capabilities from functional descriptors */
            /* But for now, nothing is checked */
            if (union_desc == NULL)
                status = USBERR_INIT_FAILED;
            break;
        }
  
        switch (fd->header.bDescriptorSubtype) {
            case USB_DESC_SUBTYPE_CS_HEADER:
                *header_desc = fd;
                if (utoh16((*header_desc)->bcdCDC) > 0x0110)
                    status = USBERR_INIT_FAILED;
                break;
            case USB_DESC_SUBTYPE_CS_UNION:
                /* Check if this union descriptor describes master for this interface */
                if (fd->uni.bMasterInterface == intf_ptr->bInterfaceNumber) {
                    /* Check if another union descriptor has not been already assigned */
                    if (*union_desc == NULL)
                        *union_desc = fd;
                    else
                        status = USBERR_INIT_FAILED;
              }
              break;
            case USB_DESC_SUBTYPE_CS_ACM:
                *acm_desc = fd;
                break;
            case USB_DESC_SUBTYPE_CS_CM:
                *cm_desc = fd;
                break;
        }
        if (status != USB_OK)
            break;
    }

    return status;
}