首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM做为USB从设备的实现(2)

ARM做为USB从设备的实现(2)

  • /****************************** Configurations ******************************/

  • static
    int __init do_config(struct usb_configuration *c)  
  • {  
  •     struct hidg_func_node *e;  
  •     int func = 0, status = 0;  

  •     if (gadget_is_otg(c->cdev->gadget)) {  
  •         c->descriptors = otg_desc;  
  •         c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;  
  •     }  

  •     list_for_each_entry(e, &hidg_func_list, node) {  
  •         status = hidg_bind_config(c, e->func, func++);  
  •         if (status)  
  •             break;  
  •     }  

  •     return status;  
  • }  

  • static
    struct usb_configuration config_driver = {  
  •     .label          = "HID Gadget",  
  •     .bind           = do_config,  
  •     .bConfigurationValue    = 1,  
  •     /* .iConfiguration = DYNAMIC */
  •     .bmAttributes       = USB_CONFIG_ATT_SELFPOWER,  
  • };  

  • /****************************** Gadget Bind ******************************/

  • static
    int __init hid_bind(struct usb_composite_dev *cdev)  
  • {  
  •     struct usb_gadget *gadget = cdev->gadget;  
  •     struct list_head *tmp;  
  •     int status, gcnum, funcs = 0;  

  •     list_for_each(tmp, &hidg_func_list)  
  •         funcs++;  

  •     if (!funcs)  
  •         return -ENODEV;  

  •     /* set up HID */
  •     printk("=============bind\n");  
  •     status = ghid_setup(cdev->gadget, funcs);  
  •     if (status < 0)  
  •         return status;  

  •     gcnum = usb_gadget_controller_number(gadget);  
  •     if (gcnum >= 0)  
  •         device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);  
  •     else
  •         device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);  


  •     /* Allocate string descriptor numbers ... note that string
  •      * contents can be overridden by the composite_dev glue.
  •      */

  •     /* device descriptor strings: manufacturer, product */
  •     snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",  
  •         init_utsname()->sysname, init_utsname()->release,  
  •         gadget->name);  
  •     status = usb_string_id(cdev);  
  •     if (status < 0)  
  •         return status;  
  •     strings_dev[STRING_MANUFACTURER_IDX].id = status;  
  •     device_desc.iManufacturer = status;  

  •     status = usb_string_id(cdev);  
  •     if (status < 0)  
  •         return status;  
  •     strings_dev[STRING_PRODUCT_IDX].id = status;  
  •     device_desc.iProduct = status;  

  •     /* register our configuration */
  •     status = usb_add_config(cdev, &config_driver);  
  •     if (status < 0)  
  •         return status;  

  •     dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");  

  •     return 0;  
  • }  

  • static
    int __exit hid_unbind(struct usb_composite_dev *cdev)  
  • {  
  •     ghid_cleanup();  
  •     return 0;  
  • }  

  • static
    int __init hidg_plat_driver_probe(struct platform_device *pdev)  
  • {  
  •     struct hidg_func_descriptor *func = pdev->dev.platform_data;  
  •     struct hidg_func_node *entry;  

  •     if (!func) {  
  •         dev_err(&pdev->dev, "Platform data missing\n");  
  •         return -ENODEV;  
  •     }  

  •     entry = kzalloc(sizeof(*entry), GFP_KERNEL);  
  •     if (!entry)  
  •         return -ENOMEM;  

  •     entry->func = func;  
  •     list_add_tail(&entry->node, &hidg_func_list);  

  •     return 0;  
  • }  

  • static
    int __devexit hidg_plat_driver_remove(struct platform_device *pdev)  
  • {  
  •     struct hidg_func_node *e, *n;  

  •     list_for_each_entry_safe(e, n, &hidg_func_list, node) {  
  •         list_del(&e->node);  
  •         kfree(e);  
  •     }  

  •     return 0;  
  • }  


  • /****************************** Some noise ******************************/


  • static
    struct usb_composite_driver hidg_driver = {  
  •     .name       = "g_hid",  
  •     .dev        = &device_desc,  
  •     .strings    = dev_strings,  
  •     .bind       = hid_bind,  
  •     .unbind     = __exit_p(hid_unbind),  
  • };  

  • static
    struct platform_driver hidg_plat_driver = {  
  •     .remove     = __devexit_p(hidg_plat_driver_remove),  
  •     .driver     = {  
  •         .name   = "hidg",  
  •         .owner  = THIS_MODULE,  
  •     },   
  • };  

  • static
    struct musb_hdrc_platform_data hidg_plat_data = {  
  •     .mode       = MUSB_PERIPHERAL,//MUSB_OTG,
  • };  

  • static
    struct platform_device hidg_plat_device = {  
  •     .name       = "hidg",  
  •     .id         = -1,  
  •     .dev        = {  
  •         //.init_name = "hidg_init"
  •         .platform_data  = &hidg_plat_data,  
  •     },  
  • };  

  • MODULE_DESCRIPTION(DRIVER_DESC);  
  • MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");  
  • MODULE_LICENSE("GPL");  

  • static
    int __init hidg_init(void)  
  • {  
  •     int status;  

  •     status = platform_device_register(&hidg_plat_device);  
  •     if(status < 0)  
  •         return status;  

  •     status = platform_driver_probe(&hidg_plat_driver, hidg_plat_driver_probe);  
  •     if (status < 0)  
  •         return status;  

  •     status = usb_composite_register(&hidg_driver);  
  •     if (status < 0)  
  •         platform_driver_unregister(&hidg_plat_driver);  

  •     return status;  
  • }  
  • module_init(hidg_init);  

  • static
    void __exit hidg_cleanup(void)  
  • {  
  •     platform_driver_unregister(&hidg_plat_driver);  
  •     usb_composite_unregister(&hidg_driver);  
  • }  
  • module_exit(hidg_cleanup);  
继承事业,薪火相传
返回列表