Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2093560
  • 博文数量: 505
  • 博客积分: 1552
  • 博客等级: 上尉
  • 技术积分: 2514
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-23 18:24
文章分类

全部博文(505)

文章存档

2019年(12)

2018年(15)

2017年(1)

2016年(17)

2015年(14)

2014年(93)

2013年(233)

2012年(108)

2011年(1)

2009年(11)

分类: LINUX

2013-03-23 11:45:34

2440 USB Gadget 存储设备的调试



众所周知,USB Gadget 的源代码,在 内核目录 driver->usb->gadget 目录下,gadget  能实现的功能有很多,可以让嵌入式设备,在PC 上实现一个存储磁盘,虚拟成一个网络设备还有, zero 设备,今天,我主要记录一下,自己,在调试SD 卡过程,碰到的问题,哎,发现,自己弄这个arm 开发板,一路碰到的都是很经典的问题,先讲一下,自己碰到的问题吧。

 

linux ,对gadget的支持,已经,有方案了,自己用的是2440,自然,选中内核的选项,就可以把2440 的udc ,编译进内核了,但是,都必须是 模块的形式,编译,才行,找到Device drivers–>USb support –> usb gadget support –> File backed Storage gadget

[*]File-backed Storage gadget testing version , 直接编译

sudo make ,这样它就会把模块也编译出来。

插入相应的模块

 insmod /etc/modules/s3c2410_udc.ko
insmod /etc/modules/g_file_storage.ko file=/dev/sdcard stall=0 removable=1

这里的驱动,涉及的文件是s3c2410_udc.c 和 file_storage.c

接上USB 线以后,就可以,识别成存储器,但是 这样的做法,只能,拷贝小文件,大文件往往会出各种问题,

别想了,问题没出在file_storage.c,这是Linux内核社区写的 ,肯定是棒子给的文件有问题,

自己的不是大牛,这两文件的分析,就算了,主要,还是讲一下,自己无所不能的搜索技术,google ,找答案,

嘿嘿,自己的问题,网上的哥们分析,还真不少,但大部分,都是,讲协议的,什么协议? 这个都是内核里写好的

看大牛的分析,还不如拿着RFC,看源代码,总的来说是不管的事。  突然google 发力,追踪到了这里 ,http://www.linuxforum.net/forum/printthread.php?Cat=&Board=embedded&main=725335&type=thread

网上牛人真多啊, 这种微妙的东西都能发现,他妈的是吃什么长大的,总之一个字,就是牛。

以防链接消失,我把关键复制下来,

tengel,我是这样加的again:
static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, struct s3c2410_request *req) {
u8 *buf;
u32 ep_csr;
unsigned bufferspace;
int is_last = 1;
unsigned avail;
int fifo_count = 0;
u32 idx;
int fifo_reg;
int again_num = 0;
struct timeval time;

idx = ep->bEndpointAddress & 0x7F;
switch (idx) {
default:
idx = 0;
case 0:
fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
break;
case 1:
fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
break;
case 2:
fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
break;
case 3:
fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
break;
case 4:
fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
break;
}

if (!req->req.length) {
return 1;
}

do_gettimeofday(&time);
if(( time.tv_sec – o_tick ) >= 10){
dprintk(DEBUG_WATCH, “last data, actual:%d, length:%d, count:%d\n”, o_actual, o_length, o_x_count);
}
o_tick = time.tv_sec;

again:
buf = req->req.buf + req->req.actual;
bufferspace = req->req.length – req->req.actual;
if (!bufferspace) {
dprintk(DEBUG_WATCH/*DEBUG_NORMAL*/, “%s: buffer full!\n”, __func__);
return -1;
}

udc_write(idx, S3C2410_UDC_INDEX_REG);
fifo_count = s3c2410_udc_fifo_count_out();
//dprintk(DEBUG_WATCH/*DEBUG_VERBOSE*/, “%s fifo count : %d\n”, __func__, fifo_count);

if (fifo_count > ep->ep.maxpacket) {
avail = ep->ep.maxpacket;
}
else {
avail = fifo_count;
}

fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);

// checking this with ep0 is not accurate as we already read a control request
if (idx != 0 && fifo_count < ep->ep.maxpacket) {
is_last = 1;
// overflowed this request? flush extra data
if (fifo_count != avail) {
req->req.status = -EOVERFLOW;
}
}
else {
is_last = (req->req.length <= req->req.actual) ? 1 : 0;
}

udc_write(idx, S3C2410_UDC_INDEX_REG);
fifo_count = s3c2410_udc_fifo_count_out();

// Only ep0 debug messages are interesting
if (idx == 0) {
dprintk(DEBUG_WATCH/*DEBUG_VERBOSE*/, “%s fifo count : %d [last %d]\n”, __func__, fifo_count,is_last);
}

if (is_last) {
if (idx == 0) {
s3c2410_udc_set_ep0_de_out(base_addr);
ep->dev->ep0state = EP0_IDLE;
}
else {
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG);
s3c2410_udc_done(ep, req, 0);
}
}
else {
if (idx == 0) {
s3c2410_udc_clear_ep0_opr(base_addr);
}
else {
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG);
}
}
}

/**/
//udc_write(idx, S3C2410_UDC_INDEX_REG);
fifo_count = s3c2410_udc_fifo_count_out();
if( (( EP_FIFO_SIZE == fifo_count) || ((req->req.length – req->req.actual) == fifo_count) )
&& (!is_last)
){
dprintk(DEBUG_NORMAL, “goto again”);
goto again;
}

return is_last;
}

分析这位仁兄的做法,对照,内核代码,发现,这哥们就是,把数据多读了几遍,哎,在这,我又得概叹几句了,

“为什么国人这么聪明,还得用棒子设计的CPU呢?”,真想不通。

瞬间,改过以后,就好使多了。


转载:http://www.qtprogrammer.org/?p=264

阅读(665) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~