/**
 * This function will run adk class driver when usb device is detected and identified
 *  as a adk class device, it will continue the enumulate process.
 *
 * @param arg the argument.
 *
 * @return the error code, RT_EOK on successfully.
 */
static rt_err_t rt_usb_adk_run(void* arg)
{
    int i = 0;
    uadkinst_t adkinst;
    uifinst_t ifinst = (uifinst_t)arg;
    udev_desc_t dev_desc;
    rt_uint16_t protocol;
    rt_err_t ret;

    /* parameter check */
    if(ifinst == RT_NULL)
    {
        rt_kprintf("the interface is not available\n");
        return -RT_EIO;
    }

    RT_DEBUG_LOG(RT_DEBUG_USB,("rt_usb_adk_run\n"));

    if(ifinst->intf_desc->bInterfaceSubClass != 0xFF) return -RT_ERROR;

    dev_desc = &ifinst->uinst->dev_desc;
    if(dev_desc->idVendor == USB_ACCESSORY_VENDOR_ID &&
            (dev_desc->idProduct == USB_ACCESSORY_PRODUCT_ID ||
             dev_desc->idProduct == USB_ACCESSORY_ADB_PRODUCT_ID))
    {
        rt_kprintf("found android accessory device\n");
    }
    else
    {
        rt_kprintf("switch device\n");

        if((ret = rt_usb_adk_get_protocol(ifinst, &protocol)) != RT_EOK)
        {
            rt_kprintf("rt_usb_adk_get_protocol failed\n");
            return ret;
        }

        if(protocol != 1)
        {
            rt_kprintf("read protocol failed\n");
            return -RT_ERROR;
        }

        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_MANUFACTURER, "Real Thread, Inc");
        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_MODEL, "ART");
        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_DESCRIPTION, "Arduino like board");
        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_VERSION, "1.0");
        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_VERSION, "www.rt-thread.org");
        rt_usb_adk_send_string(ifinst, ACCESSORY_STRING_SERIAL, "00000012345678");

        if((ret = rt_usb_adk_start(ifinst)) != RT_EOK)
        {
            rt_kprintf("rt_usb_adk_start failed\n");
            return ret;
        }

        return RT_EOK;
    }

    adkinst = rt_malloc(sizeof(struct uadkinst));
    RT_ASSERT(adkinst != RT_NULL);

    /* initilize the data structure */
    rt_memset(adkinst, 0, sizeof(struct uadkinst));
    ifinst->user_data = (void*)adkinst;

    for(i=0; i<ifinst->intf_desc->bNumEndpoints; i++)
    {
        uep_desc_t ep_desc;

        /* get endpoint descriptor from interface descriptor */
        rt_usb_get_endpoint_descriptor(ifinst->intf_desc, i, &ep_desc);
        if(ep_desc == RT_NULL)
        {
            rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
            return -RT_ERROR;
        }

        /* the endpoint type of adk class should be BULK */
        if((ep_desc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
            continue;

        /* allocate pipes according to the endpoint type */
        if(ep_desc->bEndpointAddress & USB_DIR_IN)
        {
            /* allocate an in pipe for the adk instance */
            ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_in,
                                        ifinst, ep_desc, RT_NULL);
            if(ret != RT_EOK) return ret;
        }
        else
        {
            /* allocate an output pipe for the adk instance */
            ret = rt_usb_hcd_alloc_pipe(ifinst->uinst->hcd, &adkinst->pipe_out,
                                        ifinst, ep_desc, RT_NULL);
            if(ret != RT_EOK) return ret;
        }
    }

    /* check pipes infomation */
    if(adkinst->pipe_in == RT_NULL || adkinst->pipe_out == RT_NULL)
    {
        rt_kprintf("pipe error, unsupported device\n");
        return -RT_ERROR;
    }

    /* set configuration */
    ret = rt_usb_set_configure(ifinst->uinst, 1);
    if(ret != RT_EOK) return ret;

    /* register adk device */
    adkinst->device.type  = RT_Device_Class_Char;
    adkinst->device.init = RT_NULL;
    adkinst->device.open = RT_NULL;
    adkinst->device.close = RT_NULL;
    adkinst->device.read = rt_usb_adk_read;
    adkinst->device.write = rt_usb_adk_write;
    adkinst->device.control = RT_NULL;
    adkinst->device.user_data = (void*)ifinst;

    rt_device_register(&adkinst->device, "adkdev", RT_DEVICE_FLAG_RDWR);

    return RT_EOK;
}
Example #2
0
/**
 * This function will run usb hub class driver when usb hub is detected and identified
 * as a hub class device, it will continue to do the enumulate process.
 *
 * @param arg the argument.
 * 
 * @return the error code, RT_EOK on successfully.
 */
static rt_err_t rt_usb_hub_run(void *arg)
{
    int i = 0;
    rt_err_t ret = RT_EOK;
    uep_desc_t ep_desc;
    uhubinst_t uhub;
    uinst_t uinst;
    uifinst_t ifinst = (uifinst_t)arg;
    int timeout = 300;

    /* paremeter check */
    RT_ASSERT(ifinst != RT_NULL);
    
    RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_hub_run\n"));

    /* get usb device instance */
    uinst = ifinst->uinst;

    /* create a hub instance */
    uhub = rt_malloc(sizeof(struct uhubinst));
    rt_memset(uhub, 0, sizeof(struct uhubinst));
    
    /* make interface instance's user data point to hub instance */
    ifinst->user_data = (void*)uhub;

    /* get hub descriptor head */
    ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 8);
    if(ret != RT_EOK)
    {
        rt_kprintf("get hub descriptor failed\n");
        return -RT_ERROR;        
    }

    /* get full hub descriptor */
    ret = rt_usb_hub_get_descriptor(uinst, (rt_uint8_t*)&uhub->hub_desc, 
        uhub->hub_desc.length);
    if(ret != RT_EOK)
    {
        rt_kprintf("get hub descriptor again failed\n");
        return -RT_ERROR;        
    }    

    /* get hub ports number */
    uhub->num_ports = uhub->hub_desc.num_ports;
    uhub->hcd = uinst->hcd;
    uhub->self = uinst;

    /* reset all hub ports */
    for (i = 0; i < uhub->num_ports; i++)
    {
        rt_usb_hub_set_port_feature(uhub, i + 1, PORT_FEAT_POWER);
        rt_thread_delay(uhub->hub_desc.pwron_to_good
            * 2 * RT_TICK_PER_SECOND / 1000 );
    }

    if(ifinst->intf_desc->bNumEndpoints != 1) 
        return -RT_ERROR;

    /* get endpoint descriptor from interface descriptor */
    rt_usb_get_endpoint_descriptor(ifinst->intf_desc, 0, &ep_desc);
    if(ep_desc == RT_NULL)
    {
        rt_kprintf("rt_usb_get_endpoint_descriptor error\n");
        return -RT_ERROR;
    }

    /* the endpoint type of hub class should be interrupt */        
    if( USB_EP_ATTR(ep_desc->bmAttributes) == USB_EP_ATTR_INT)
    {
        /* the endpoint direction of hub class should be in */
        if(ep_desc->bEndpointAddress & USB_DIR_IN)
        {    
            /* allocate a pipe according to the endpoint type */
            rt_usb_hcd_alloc_pipe(uinst->hcd, &uhub->pipe_in, ifinst, 
                ep_desc, rt_usb_hub_irq);
        }
        else return -RT_ERROR;
    }

    /* parameter check */
     RT_ASSERT(uinst->hcd != RT_NULL);
    
    rt_usb_hcd_int_xfer(uinst->hcd, uhub->pipe_in, uhub->buffer, 
        uhub->pipe_in->ep.wMaxPacketSize, timeout);
    
    return RT_EOK;
}