refer to and thanks
usb spec
国嵌usb视频linux2.6.32.2 uboot2009.11
首先了解linux de yousb编程层次
有颜色的部分是需要自己写代码的,但很多设备的驱动已经写好放在在driver目录下,但可能没配置。
而usb主机控制器驱动和udc驱动在linux内核已经实现,不必写代码。但可能没配置,所以必要时make menuconfig配置一下。
即
①开发板可以工作成主机,usb键盘鼠标可以接到上面,称为usb hid设备。要在开发板上编写hid驱动,以支持hid设备。当然在hid设备上,比如一个单片机做成的hid设备,也要写程序。
注:hid:human interface device 人机接口设备。比如鼠标键盘手柄等。不光是usb hid叫hid,ps/2的鼠标也叫hid,即ps/2 hid.
②开发板可以工作成设备,比如当成一个网卡,接到pc上面,此时开发板成为gadget设备。在开发板上要编写gadget驱动。
/****************************************************************板子作host,和usb设备相连**********************************************/
需要有主控制器驱动和相应设备驱动
需要有udc驱动和相应gadget设备驱动
usb spec
国嵌usb视频linux2.6.32.2 uboot2009.11
首先了解linux de yousb编程层次
有颜色的部分是需要自己写代码的,但很多设备的驱动已经写好放在在driver目录下,但可能没配置。
而usb主机控制器驱动和udc驱动在linux内核已经实现,不必写代码。但可能没配置,所以必要时make menuconfig配置一下。
即
①开发板可以工作成主机,usb键盘鼠标可以接到上面,称为usb hid设备。要在开发板上编写hid驱动,以支持hid设备。当然在hid设备上,比如一个单片机做成的hid设备,也要写程序。
注:hid:human interface device 人机接口设备。比如鼠标键盘手柄等。不光是usb hid叫hid,ps/2的鼠标也叫hid,即ps/2 hid.
②开发板可以工作成设备,比如当成一个网卡,接到pc上面,此时开发板成为gadget设备。在开发板上要编写gadget驱动。
/****************************************************************板子作host,和usb设备相连**********************************************/
需要有主控制器驱动和相应设备驱动
/*板子作host,和usb设备相连*/
//配置内核以支持massstorage(以u盘为例)
//支持热插拔
general setup-->
[*]configure standard kernel feature(for small systems)-->
[*]support for hot-pluggable devices
//scsi设备驱动(u盘被当做scsi设备,就像鼠标被当做hid设备)
device driver-->
scsi device support-->
[*]scsi device support
[*]scsi disk support
[*]scsi generic support
//usb主控制器驱动(主要是support for host-side usb)和设备驱动(主要是usb mass storage support)
device driver-->
[*]usb support-->
<*>support for host-side usb
[*]usb device filesystem
<*>ohci hcd support
<*>usb mass storage support
[*]usb monitor
//支持u盘内部文件系统,如fat32
file systems-->
dos/fat/nt filesystems-->
<*>msdos fs support
<*>vfat(windoww-95)fs support
(936)default codepage for fat
(cp936)default iocharset for fat
partition types-->
[*]pc bios(msdos partition table)support
--*-- native language suport-->
<*>simplified chinese charset(cp936,gb2312)
<*>nls utf-8
/*板子作host*/
//配置内核以支持usb鼠标键盘
//usb主控制器驱动(③中已经选过了)
device driver-->
[*]usb support-->
<*>support for host-side usb
<*>ohci hcd support
//hid驱动(usb设备驱动)
device driver-->
hid device-->
<*>usb human interface device(full hid)support
/************************************************************板子作device,和pc相连**********************************************/
需要有udc驱动和相应gadget设备驱动
/*板子作device,和pc相连*/
//将mini2440模拟成网卡(rndis,remote network device)
//udc驱动是usb peripheral controler(s3c2410 usb device controler)
//gadget驱动是ethenet gadget(with cdc ethenet support)
//(注:cdc communication device class,acm abstract control model)
device driver-->
[*]usb support-->
[*]usb gadget support-->
[*]usb peripheral controler(s3c2410 usb device controler)
[M]usb gatget drivers
[M]ethenet gadget(with cdc ethenet support)
[*]rndis support
//(当然也可将其编译进内核)
//执行
make
make modules
//考linux/driver/usb/gadget/g_ether.ko到板子
//启动板子(我的是uboot启动的linux2.6.32.2,先用mkimage将uImage转换一下,直接make uImage),在pc终端执行
insmod g_ether.ko
//连好线,会发现电脑有发现新硬件的提示,找到pc上的驱动信息linux.inf安装一下即可
//现在板子和pc上会各多出一个网卡,板子的是usb0,现在为新出现的这对网卡设置一下ip(不要和原来的ip在同一网段)
//在板子上执行ifconfig usb0 192.168.2.6
//在pc上执行,将新出现的网卡设置ip为192.168.1.7
//现在可以互相ping通
/*板子作device,和pc相连*/
//将mini2440模拟成串口
//udc驱动是usb peripheral controler(s3c2410 usb device controler)
//gadget驱动是Serial Gadget (with CDC ACM and CDC OBEX support)
device driver-->
[*]usb support-->
[*]usb modem(cdc acm)support
[*]usb gadget support
[*]usb peripheral controler(s3c2410 usb device controler)
[M]usb gatget drivers
[M]Serial Gadget (with CDC ACM and CDC OBEX support)
//执行
make
make modules
//考linux/driver/usb/gadget/g_serial.ko到板子
//启动板子,在pc终端执行
insmod g_ether.ko
//连好线,会发现电脑有发现新硬件的提示,找到pc上的驱动信息gserial.inf安装一下即可
//现在板子和pc上会各多出一个串口,板子上的是/dev/ttyGS0
//在pc新开一个串口,监视一下新出现的串口
//在终端执行echo hello > /dev/ttyGS0
//效果如下图
/*板子作device,和pc相连*/
//pc上读取mini2440的板载sdcard
//udc驱动是usb peripheral controler(s3c2410 usb device controler)
//gadget驱动是File-backed Storage Gadget
device driver-->
[*]usb support-->
[*]usb modem(cdc acm)support
[*]usb gadget support
[*]usb peripheral controler(s3c2410 usb device controler)
[M]usb gatget drivers
[M]File-backed Storage Gadget
//执行
make modules
//考linux/driver/usb/gadget/g_file_storage.ko 到板子
//启动板子,插上sdcard,在pc终端执行
insmod g_file_storage.ko file=/dev/sdcard stall=0 removable=1
//此时终端会发出如下信息
g_file_storage gadget: File-backed Storage Gadget, version: 20 November 2008
g_file_storage gadget: Number of LUNs=1
g_file_storage gadget-lun0: ro=0, file: /dev/sdcard
//连好线,终端发出如下信息
g_file_storage gadget: full speed config #1
//片刻之后,电脑上会多出一个盘符,恩。就是sdcard了
/dev/sdcard是sd卡的设备文件,所以想在pc读写板载sdcard,首先应使sdcard在板子上工作正常。mini2440读写sdcard(fat32分区)已经正常。
//同时可以想到,如果用
insmod g_file_storage.ko file=/dev/mtdblock3 stall=0 removable=1
//此时pc上的新盘符代表nandflash的第3个分区(默认yaffs所在分区)。所以,如果nand容量很大,如8G,则可以单独分出一个区开放给用户使用。
//在读写大点的文件时,出现"无法复制xxx:路径太深"的错误,解决如下:
//修改linux/drivers/usb/gadget/file_storage.c的一个函数,remove一行add一行,如下
static int fsg_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{
struct fsg_dev *fsg = get_gadget_data(gadget);
int rc;
int w_length = le16_to_cpu(ctrl->wLength);
++fsg->ep0_req_tag; // Record arrival of a new request
fsg->ep0req->context = NULL;
fsg->ep0req->length = 0;
dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
rc = class_setup_req(fsg, ctrl);
else
rc = standard_setup_req(fsg, ctrl);
/* Respond with data/status or defer until later? */
if (rc >= 0 && rc != DELAYED_STATUS) {
rc = min(rc, w_length);
fsg->ep0req->length = rc;
//fsg->ep0req->zero = rc < w_length;/**********************remove*****************/
fsg->ep0req->zero =rc < w_length&&(rc % gadget->ep0->maxpacket)==0;/******************add********************/
fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
"ep0-in" : "ep0-out");
rc = ep0_queue(fsg);
}
/* Device either stalls (rc < 0) or reports success */
return rc;
}
//修改linux/drivers/usb/gadget/s3c2410_udc.c 的一个函数,add 3行,如下
static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
{
struct s3c2410_request *req;
int is_in = ep->bEndpointAddress & USB_DIR_IN;
u32 ep_csr1;
u32 idx;
handle_ep_again:/********************add*********************************/
if (likely (!list_empty(&ep->queue)))
req = list_entry(ep->queue.next,
struct s3c2410_request, queue);
else
req = NULL;
idx = ep->bEndpointAddress & 0x7F;
if (is_in) {
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
idx, ep_csr1, req ? 1 : 0);
if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
dprintk(DEBUG_VERBOSE, "st\n");
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
S3C2410_UDC_IN_CSR1_REG);
return;
}
if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
s3c2410_udc_write_fifo(ep,req);
}
} else {
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
S3C2410_UDC_OUT_CSR1_REG);
return;
}
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
s3c2410_udc_read_fifo(ep,req);
if(s3c2410_udc_fifo_count_out())/****************************add*************************/
goto handle_ep_again;/**********************add****************************/
}
}
}
//重新
make
make modules
//重新烧写内核和模块