/** * 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; }
/** * 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; }