zoukankan      html  css  js  c++  java
  • s3c6410 linux gadget hid驱动

    s3c6410 linux gadget hid驱动调了我一个多星期了今天终于搞定了,来跟大家分享下.

    上一个星期纠结了一个星期的寄存器,试了N次,不管把3.1和3.7的hid驱动移植过来也是一样的情况,所以这星期直接从问题本身着手一个个找,一个个对比,终于解决了。

    我用的内核是linux2.6.38的,最开始的时候开发板是可以当U盘用的,而使用hid功能的时候出现如下问题:

    g_hid gadget: hid_setup crtl_request : bRequestType:0x21 bRequest:0xa Value:0x0
    g_hid gadget: Unknown request 0xa
    s3c-hsotg s3c-hsotg: writen DxEPCTL=0x04228000 to 00000900 (DxEPCTL=0x00208000)
    s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
    s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
    s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no req (DxEPCTl=0x00028000)
    s3c-hsotg s3c-hsotg: S3C_GINTSTS_USBSusp
    这个是我把debug信息打开后打印出来的信息,前面一直以为是device的时钟没有设置对,device的时钟应该设置为48M,但是结果不是这里的问题,怎么修改时钟效果都是一样,所以上个星期一个寄存器一个寄存器的对,修改完后发现还是一样的问题。所以开始研究这个:Unknown request 0xa

    hid的大致流程是s3c_hsotg.c->composite.c->f_hid.c具体流程网上有很多这里我就不作说明了。

    资料:

    http://blog.csdn.net/wuyuwei45/article/details/8930830

    http://blog.csdn.net/fanqipin/article/details/8450694

    纠结了一个星期后,中间花了几个小时把2416的hid调好的,最后没办法所以决定一步步对.

    6410的当host发送请求0xa时就直接出现了上面的错误,但是2416当host发送0xa时也会出现-95的错误但是host端会继续发送0x06和0x09请求,请查看usb协议这里就不多说了。

    6410与2416在接收到0xa请求时的操作基本一样,不同的是2416在接收到0xa后,会忽略这个请求然后向host发送一个空包,这样host会继续发送其它的请求,而6410在接收到0xa后忽略了,但是没有向host端发送任何数据,所以导致后面的操作无法进行.

    所以现在的工作就是当device收到0xa后,向host端发送一个空包,让枚举继续下去.
    主要修改就在s3c_hsotg.c里面的s3c_hsotg_process_control函数,整个过程我就不在这分析了,我也不是很懂,哈哈。

    	/* as a fallback, try delivering it to the driver to deal with */
    	if (ret == 0 && hsotg->driver) {
    		ret = hsotg->driver->setup(&hsotg->gadget, ctrl);
    		if (ret < 0)
    			dev_dbg(hsotg->dev, "driver->setup() ret %d
    ", ret);
    	}


    这里是接收到请求后由composite.c里面的composite_setup进行处理,当接收到0xa后这里会返回-95的错误,我们接着往下看:

    	/* the request is either unhandlable, or is not formatted correctly
    	 * so respond with a STALL for the status stage to indicate failure.
    	 */
    
    	if (ret < 0) {
    		u32 reg;
    		u32 ctrl;
    
    		dev_dbg(hsotg->dev, "ep0 stall (dir=%d)
    ", ep0->dir_in);
    		reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;
    
    		/* S3C_DxEPCTL_Stall will be cleared by EP once it has
    		 * taken effect, so no need to clear later. */
    
    		ctrl = readl(hsotg->regs + reg);
    		ctrl |= S3C_DxEPCTL_Stall;
    		ctrl |= S3C_DxEPCTL_CNAK;
    		writel(ctrl, hsotg->regs + reg);
    
    		dev_dbg(hsotg->dev,
    			"writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)
    ",
    			ctrl, reg, readl(hsotg->regs + reg));
    
    		/* don't belive we need to anything more to get the EP
    		 * to reply with a STALL packet */
    	}

    当返回-95后只对DIEPCTL0进行了相关操作,具体设置请查看6410 datasheet

    所以我们要在这加上发一个空包的过程,看s3c_hsotg.c你会发现,里面有这样一个函数:s3c_hsotg_send_zlp

    这个函数的功能就是向host发送一个空包的过程,当然不能全部copy过来,全部copy过来是会有问题的,所以我的修改如下:

    	/* the request is either unhandlable, or is not formatted correctly
    	 * so respond with a STALL for the status stage to indicate failure.
    	 */
    
    	if (ret < 0) {
    		u32 reg;
    		u32 ctrl;
    
    		dev_dbg(hsotg->dev, "ep0 stall (dir=%d)
    ", ep0->dir_in);
    		reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0;
    
    		/* S3C_DxEPCTL_Stall will be cleared by EP once it has
    		 * taken effect, so no need to clear later. */
    		if(ret != -95) {
    			ctrl = readl(hsotg->regs + reg);
    			ctrl |= S3C_DxEPCTL_Stall;
    			ctrl |= S3C_DxEPCTL_CNAK;
    			writel(ctrl, hsotg->regs + reg);
    		}
    		else {
    			/* issue a zero-sized packet to terminate this */
    			writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
    			       S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0));
    
    			ctrl = readl(hsotg->regs + reg);
    			ctrl |= S3C_DxEPCTL_CNAK;  /* clear NAK set by core */
    			ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */
    			ctrl |= S3C_DxEPCTL_USBActEp;
    			writel(ctrl, hsotg->regs + reg);
    		}
    
    		dev_dbg(hsotg->dev,
    			"writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)
    ",
    			ctrl, reg, readl(hsotg->regs + reg));
    
    		/* don't belive we need to anything more to get the EP
    		 * to reply with a STALL packet */
    	}

    当if(ret < 0)里改为如下,同时保留原来的设置,以勉后面出现问题,这样修改后当host发送0xa给device device会回一个空包给host 这样host会继续后面的操作,这样你就可以在你的电脑硬件管理里面看到你的hid设备了。

    水平有限 ,如有错误请指出。

     

  • 相关阅读:
    分布式缓存负载均衡的规则处理:虚拟节点对一致性哈希的改进
    GoldenGate实时投递数据到大数据平台(6)– HDFS
    OGG 12.3中支持系统procedure复制的几点说明
    使用GoldenGate初始化的两种方式
    传统OGG与Microservice Architecture OGG的通信
    利用Oracle GoldenGate记录源系统所有表的操作
    GoldenGate实时投递数据到大数据平台(5)
    GoldenGate 12.2抽取Oracle 12c多租户配置过程
    GoldenGate实时投递数据到大数据平台(4)- ElasticSearch 2.x
    GoldenGate实时投递数据到大数据平台(3)- Apache Flume
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3181667.html
Copyright © 2011-2022 走看看