linux usb ffs代码解读

  • 这部分的思想是和字符设备驱动是一样的,注册好设备function,然后初始化好结构体,设备与驱动匹配,执行相应文件描述符设置好的回调函数

  • 下边是f_fs.c文件中代码大致捋了一下,我觉着这样看调用更直观一些

 - `
DECLARE_USB_FUNCTION_INIT(ffs, ffs_alloc_inst, ffs_alloc){

    //我们把宏定义化简之后,注册什么的都有了
    static struct usb_function_driver ffsusb_func = {		//这里定义的是一个usb_function_driver驱动
            .name = __stringify(ffs),				
            .mod  = THIS_MODULE,					
            .alloc_inst = ffs_alloc_inst,				
            .alloc_func = ffs_alloc,				
        };								
        MODULE_ALIAS("usbfunc:"__stringify(ffs));

    static int __init ffsmod_init(void)			
        {								
            return usb_function_register(&ffsusb_func);	 //这里主要是把这个uac2usb_func这个usb_function_driver放入func_list链表
        }								
    static void __exit ffsmod_exit(void)			
        {								
            usb_function_unregister(&ffsusb_func);		
        }								
    module_init(ffsmod_init);					
    module_exit(ffsmod_init)

}

static struct usb_function *ffs_alloc(struct usb_function_instance *fi)
{
	struct ffs_function *func;
	ENTER();
	func = kzalloc(sizeof(*func), GFP_KERNEL);
	if (unlikely(!func))
		return ERR_PTR(-ENOMEM);
	func->function.name    = "Function FS Gadget";
	func->function.bind    = ffs_func_bind;
	func->function.unbind  = ffs_func_unbind;
	func->function.set_alt = ffs_func_set_alt;
	func->function.disable = ffs_func_disable;
	func->function.setup   = ffs_func_setup;
	func->function.req_match = ffs_func_req_match;
	func->function.suspend = ffs_func_suspend;
	func->function.resume  = ffs_func_resume;
	func->function.free_func = ffs_free;
	return &func->function;
}

/* Devices management *******************************************************/

static LIST_HEAD(ffs_devices);
static struct usb_function_instance *ffs_alloc_inst(void){
    ffs_devices
    struct f_fs_opts *opts;
    struct ffs_dev *dev;
	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
	if (!opts)
		return ERR_PTR(-ENOMEM);
	opts->func_inst.set_inst_name = ffs_set_inst_name;
	opts->func_inst.free_func_inst = ffs_free_inst;
    dev = _ffs_alloc_dev(){
        /* Driver's main init/cleanup functions */
        functionfs_init(){
            static struct file_system_type ffs_fs_type = {
                .owner		= THIS_MODULE,
                .name		= "functionfs",
                .init_fs_context = ffs_fs_init_fs_context,
                .parameters	= &ffs_fs_fs_parameters,
                .kill_sb	= ffs_fs_kill_sb,
            };
            MODULE_ALIAS_FS("functionfs");
            ret = register_filesystem(&ffs_fs_type);
            pr_info("file system registered\n");
        }
        list_add(&dev->entry, &ffs_devices);
    }
    opts->dev = dev;
	dev->opts = opts;
    config_group_init_type_name(&opts->func_inst.group, "",
				    &ffs_func_type);
    
}

static int ffs_func_set_alt(struct usb_function *f,
			    unsigned interface, unsigned alt)
{
	struct ffs_function *func = ffs_func_from_usb(f){
	    return container_of(f, struct ffs_function, function);
    }
    ..
    ffs->func = func;
    ffs_func_eps_enable(func){
        config_ep_by_speed(func->gadget, &func->function, ep->ep);
    } 
}

int ffs_func_bind(struct usb_configuration *c,
			 struct usb_function *f)
{
    struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);{
        /*
        * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
        * configurations are bound in sequence with list_for_each_entry,
        * in each configuration its functions are bound in sequence
        * with list_for_each_entry, so we assume no race condition
        * with regard to ffs_opts->bound access
        */
        ret = functionfs_bind(func->ffs, c->cdev);{
            first_id = usb_string_ids_n(cdev, ffs->strings_count);
            ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
            ffs->ep0req->complete = ffs_ep0_complete;
	        ffs->ep0req->context = ffs;
            ffs->gadget = cdev->gadget;
            ffs_data_get(ffs);{
                refcount_inc(&ffs->ref);
            }
        }
    }
	struct ffs_function *func = ffs_func_from_usb(f);
    _ffs_func_bind(c, f){
        struct ffs_function *func = ffs_func_from_usb(f);
        vla_group(d);
        vla_item_with_sz(d, struct ffs_ep, eps, ffs->eps_count);
        vla_item_with_sz(d, struct usb_descriptor_header *, fs_descs,
            full ? ffs->fs_descs_count + 1 : 0);
        vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
            high ? ffs->hs_descs_count + 1 : 0);
        vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
            super ? ffs->ss_descs_count + 1 : 0);
        
        if (likely(full)) {
		func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
		fs_len = ffs_do_descs(ffs->fs_descs_count,
				      vla_ptr(vlabuf, d, raw_descs),
				      d_raw_descs__sz,
				      __ffs_func_bind_do_descs, func);
    }



}

===========
int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
				    struct usb_descriptor_header *desc,
				    void *priv){


}
static const struct fs_context_operations ffs_fs_context_ops = {
	.free		= ffs_fs_free_fc,
	.parse_param	= ffs_fs_parse_param,
	.get_tree	= ffs_fs_get_tree,
};
/*
 * Set up the superblock for a mount.
 */
static int ffs_fs_get_tree(struct fs_context *fc){

    struct ffs_data	*ffs;
    ffs = ffs_data_new(fc->source){
        ffs->state = FFS_READ_DESCRIPTORS;
    }
    ffs->dev_name = kstrdup(fc->source, GFP_KERNEL);
    ffs_dev = ffs_acquire_dev(ffs->dev_name);{

        struct ffs_dev *ffs_dev;
        ffs_dev = _ffs_find_dev(dev_name);
    }
    return get_tree_nodev(fc, ffs_sb_fill){

        //设备树??
        int ffs_sb_fill(struct super_block *sb, struct fs_context *fc){
            struct ffs_sb_fill_data *data = fc->fs_private;
            struct inode	*inode;
            struct ffs_data	*ffs = data->ffs_data;

            sb->s_fs_info        = ffs;
            sb->s_blocksize      = PAGE_SIZE;
            sb->s_blocksize_bits = PAGE_SHIFT;

            /* EP0 file */
            ffs_sb_create_file(sb, "ep0", ffs,&ffs_ep0_operations)
            
            return 0;
        }

    }
}


static const struct file_operations ffs_ep0_operations = {
	.llseek =	no_llseek,

	.open =		ffs_ep0_open,
	.write =	ffs_ep0_write,
	.read =		ffs_ep0_read,
	.release =	ffs_ep0_release,
	.unlocked_ioctl =	ffs_ep0_ioctl,
	.poll =		ffs_ep0_poll,
};

ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
			     size_t len, loff_t *ptr)
{
    char *data;
    /* Check state */
	switch (ffs->state) {
        case FFS_READ_DESCRIPTORS:
	    case FFS_READ_STRINGS:
                data = ffs_prepare_buffer(buf, len){
                    char *data;
                    data = kmalloc(len, GFP_KERNEL);
                    copy_from_user(data, buf, len)

                }
                /* Handle data */
            if (ffs->state == FFS_READ_DESCRIPTORS) {
                pr_info("read descriptors\n");
                ret = __ffs_data_got_descs(ffs, data, len){

                    ret = ffs_do_descs(counts[i], data, len,
				   __ffs_data_do_entity, &helper){
                        /* Record "descriptor" entity */
		                ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv);
                        ret = ffs_do_single_desc(data, len, entity, priv,&current_class);

                   }
                }

                ffs->state = FFS_READ_STRINGS;
                ret = len;
            } else {
                pr_info("read strings\n");
                ret = __ffs_data_got_strings(ffs, data, len);

                ret = ffs_epfiles_create(ffs);

                ffs->state = FFS_ACTIVE;
              
                ret = ffs_ready(ffs);
                return len;
            }
            break;
    }
}`

更细节的地方还没研究明白,现在是一边看代码一边猜,因为这部分调用是再device端的deamon执行时的,所以结合了相应的程序看,主要是想通过裸usb节点传输,现在速度慢,想提速,看了这部分代码,找不到能提速的点啊!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值