您当前的位置:首页 > IT编程 > C++
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:C++ usb_add_function函数代码示例

51自学网 2021-06-03 09:18:43
  C++
这篇教程C++ usb_add_function函数代码示例写得很实用,希望能帮到您。

本文整理汇总了C++中usb_add_function函数的典型用法代码示例。如果您正苦于以下问题:C++ usb_add_function函数的具体用法?C++ usb_add_function怎么用?C++ usb_add_function使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。

在下文中一共展示了usb_add_function函数的27个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: cdc_do_config

static __init int cdc_do_config(struct usb_configuration *c){	struct fsg_opts *fsg_opts;	int ret;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	f_ecm = usb_get_function(fi_ecm);	if (IS_ERR(f_ecm))		return PTR_ERR(f_ecm);	ret = usb_add_function(c, f_ecm);	if (ret < 0)		goto err_func_ecm;	/* implicit port_num is zero */	f_acm_multi = usb_get_function(fi_acm);	if (IS_ERR(f_acm_multi)) {		ret = PTR_ERR(f_acm_multi);		goto err_func_acm;	}	ret = usb_add_function(c, f_acm_multi);	if (ret)		goto err_conf;	f_msg_multi = usb_get_function(fi_msg);	if (IS_ERR(f_msg_multi)) {		ret = PTR_ERR(f_msg_multi);		goto err_fsg;	}	fsg_opts = fsg_opts_from_func_inst(fi_msg);	ret = fsg_common_run_thread(fsg_opts->common);	if (ret)		goto err_run;	ret = usb_add_function(c, f_msg_multi);	if (ret)		goto err_run;	return 0;err_run:	usb_put_function(f_msg_multi);err_fsg:	usb_remove_function(c, f_acm_multi);err_conf:	usb_put_function(f_acm_multi);err_func_acm:	usb_remove_function(c, f_ecm);err_func_ecm:	usb_put_function(f_ecm);	return ret;}
开发者ID:AeroGirl,项目名称:VAR-SOM-AM33-SDK7-Kernel,代码行数:57,


示例2: gser_bind_config

/** * gser_bind_config - add a generic serial function to a configuration * @c: the configuration to support the serial instance * @port_num: /dev/ttyGS* port this interface will use * Context: single threaded during gadget setup * * Returns zero on success, else negative errno. * * Caller must have called @gserial_setup() with enough ports to * handle all the ones it binds.  Caller is also responsible * for calling @gserial_cleanup() before module unload. */int gser_bind_config(struct usb_configuration *c, u8 port_num){	struct f_gser	*gser;	int		status;	/* REVISIT might want instance-specific strings to help	 * distinguish instances ...	 */	/* maybe allocate device-global string ID */	if (gser_string_defs[0].id == 0) {		status = usb_string_id(c->cdev);		if (status < 0)			return status;		gser_string_defs[0].id = status;	}	/* allocate and initialize one new instance */	gser = kzalloc(sizeof *gser, GFP_KERNEL);	if (!gser)		return -ENOMEM;#ifdef CONFIG_MODEM_SUPPORT	spin_lock_init(&gser->lock);#endif	gser->port_num = port_num;	gser->port.func.name = "gser";	gser->port.func.strings = gser_strings;	gser->port.func.bind = gser_bind;	gser->port.func.unbind = gser_unbind;	gser->port.func.set_alt = gser_set_alt;	gser->port.func.disable = gser_disable;	gser->transport		= gserial_ports[port_num].transport;#ifdef CONFIG_MODEM_SUPPORT	/* We support only three ports for now */	if (port_num == 0)		gser->port.func.name = "modem";	else if (port_num == 1)		gser->port.func.name = "nmea";	else//zz		gser->port.func.name = "at";//zz	gser->port.func.setup = gser_setup;	gser->port.connect = gser_connect;	gser->port.get_dtr = gser_get_dtr;	gser->port.get_rts = gser_get_rts;	gser->port.send_carrier_detect = gser_send_carrier_detect;	gser->port.send_ring_indicator = gser_send_ring_indicator;	gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;	gser->port.disconnect = gser_disconnect;	gser->port.send_break = gser_send_break;#endif	status = usb_add_function(c, &gser->port.func);	if (status)		kfree(gser);	return status;}
开发者ID:forumber,项目名称:android_kernel_zte_bladevec4g,代码行数:72,


示例3: ncm_do_config

static int __init ncm_do_config(struct usb_configuration *c){	int status;	/* FIXME alloc iConfiguration string, set it in c->strings */	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	f_ncm = usb_get_function(f_ncm_inst);	if (IS_ERR(f_ncm)) {		status = PTR_ERR(f_ncm);		return status;	}	status = usb_add_function(c, f_ncm);	if (status < 0) {		usb_put_function(f_ncm);		return status;	}	return 0;}
开发者ID:19Dan01,项目名称:linux,代码行数:25,


示例4: msg_do_config

static int msg_do_config(struct usb_configuration *c){	struct fsg_opts *opts;	int ret;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	opts = fsg_opts_from_func_inst(fi_msg);	f_msg = usb_get_function(fi_msg);	if (IS_ERR(f_msg))		return PTR_ERR(f_msg);	ret = fsg_common_run_thread(opts->common);	if (ret)		goto put_func;	ret = usb_add_function(c, f_msg);	if (ret)		goto put_func;	return 0;put_func:	usb_put_function(f_msg);	return ret;}
开发者ID:020gzh,项目名称:linux,代码行数:30,


示例5: cdc_do_config

static __init int cdc_do_config(struct usb_configuration *c){	int ret;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	ret = ecm_bind_config(c, host_mac, the_dev);	if (ret < 0)		return ret;	/* implicit port_num is zero */	f_acm_multi = usb_get_function(fi_acm);	if (IS_ERR(f_acm_multi))		return PTR_ERR(f_acm_multi);	ret = usb_add_function(c, f_acm_multi);	if (ret)		goto err_conf;	ret = fsg_bind_config(c->cdev, c, &fsg_common);	if (ret < 0)		goto err_fsg;	return 0;err_fsg:	usb_remove_function(c, f_acm_multi);err_conf:	usb_put_function(f_acm_multi);	return ret;}
开发者ID:OliverGesch,项目名称:linux,代码行数:33,


示例6: thor_func_init

static int thor_func_init(struct usb_configuration *c){	struct f_thor *f_thor;	int status;	debug("%s: cdev: 0x%p/n", __func__, c->cdev);	f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor));	if (!f_thor)		return -ENOMEM;	memset(f_thor, 0, sizeof(*f_thor));	f_thor->usb_function.name = "f_thor";	f_thor->usb_function.bind = thor_func_bind;	f_thor->usb_function.unbind = thor_unbind;	f_thor->usb_function.setup = thor_func_setup;	f_thor->usb_function.set_alt = thor_func_set_alt;	f_thor->usb_function.disable = thor_func_disable;	status = usb_add_function(c, &f_thor->usb_function);	if (status)		free(f_thor);	return status;}
开发者ID:rck2015,项目名称:u-boot-xlnx,代码行数:26,


示例7: acc_bind_config

static int acc_bind_config(struct usb_configuration *c){	struct acc_dev *dev;	int ret;	printk(KERN_INFO "acc_bind_config/n");	dev = kzalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return -ENOMEM;	/* allocate a string ID for our interface */	if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {		ret = usb_string_id(c->cdev);		if (ret < 0)			return ret;		acc_string_defs[INTERFACE_STRING_INDEX].id = ret;		acc_interface_desc.iInterface = ret;	}	spin_lock_init(&dev->lock);	init_waitqueue_head(&dev->read_wq);	init_waitqueue_head(&dev->write_wq);	atomic_set(&dev->open_excl, 0);	INIT_LIST_HEAD(&dev->tx_idle);	INIT_DELAYED_WORK(&dev->work, acc_work);	dev->cdev = c->cdev;	dev->function.name = "accessory";	dev->function.strings = acc_strings,	dev->function.descriptors = fs_acc_descs;	dev->function.hs_descriptors = hs_acc_descs;	dev->function.bind = acc_function_bind;	dev->function.unbind = acc_function_unbind;	dev->function.setup = acc_function_setup;	dev->function.set_alt = acc_function_set_alt;	dev->function.disable = acc_function_disable;	dev->function.disabled = 1;	/* _acc_dev must be set before calling usb_gadget_register_driver */	_acc_dev = dev;	ret = misc_register(&acc_device);	if (ret)		goto err1;	ret = usb_add_function(c, &dev->function);	if (ret)		goto err2;	return 0;err2:	misc_deregister(&acc_device);err1:	kfree(dev);	printk(KERN_ERR "USB accessory gadget driver failed to initialize/n");	return ret;}
开发者ID:abenagiel,项目名称:android_kernel_fih_msm7x30,代码行数:59,


示例8: eth_do_config

/* * We _always_ have an ECM, CDC Subset, or EEM configuration. */static int __init eth_do_config(struct usb_configuration *c){	int status = 0;	/* FIXME alloc iConfiguration string, set it in c->strings */	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	if (use_eem) {		f_eem = usb_get_function(fi_eem);		if (IS_ERR(f_eem))			return PTR_ERR(f_eem);		status = usb_add_function(c, f_eem);		if (status < 0)			usb_put_function(f_eem);		return status;	} else if (can_support_ecm(c->cdev->gadget)) {		f_ecm = usb_get_function(fi_ecm);		if (IS_ERR(f_ecm))			return PTR_ERR(f_ecm);		status = usb_add_function(c, f_ecm);		if (status < 0)			usb_put_function(f_ecm);		return status;	} else {		f_geth = usb_get_function(fi_geth);		if (IS_ERR(f_geth))			return PTR_ERR(f_geth);		status = usb_add_function(c, f_geth);		if (status < 0)			usb_put_function(f_geth);		return status;	}}
开发者ID:19Dan01,项目名称:linux,代码行数:47,


示例9: acm_ms_do_config

/* * We _always_ have both ACM and mass storage functions. */static int acm_ms_do_config(struct usb_configuration *c){	struct fsg_opts *opts;	int	status;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	opts = fsg_opts_from_func_inst(fi_msg);	f_acm = usb_get_function(f_acm_inst);	if (IS_ERR(f_acm))		return PTR_ERR(f_acm);	f_msg = usb_get_function(fi_msg);	if (IS_ERR(f_msg)) {		status = PTR_ERR(f_msg);		goto put_acm;	}	status = usb_add_function(c, f_acm);	if (status < 0)		goto put_msg;	status = fsg_common_run_thread(opts->common);	if (status)		goto remove_acm;	status = usb_add_function(c, f_msg);	if (status)		goto remove_acm;	return 0;remove_acm:	usb_remove_function(c, f_acm);put_msg:	usb_put_function(f_msg);put_acm:	usb_put_function(f_acm);	return status;}
开发者ID:Chong-Li,项目名称:cse522,代码行数:46,


示例10: audio_do_config

static int audio_do_config(struct usb_configuration *c){	int status;	/* FIXME alloc iConfiguration string, set it in c->strings */	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}#ifdef CONFIG_GADGET_UAC1	f_uac1 = usb_get_function(fi_uac1);	if (IS_ERR(f_uac1)) {		status = PTR_ERR(f_uac1);		return status;	}	status = usb_add_function(c, f_uac1);	if (status < 0) {		usb_put_function(f_uac1);		return status;	}#else	f_uac2 = usb_get_function(fi_uac2);	if (IS_ERR(f_uac2)) {		status = PTR_ERR(f_uac2);		return status;	}	status = usb_add_function(c, f_uac2);	if (status < 0) {		usb_put_function(f_uac2);		return status;	}#endif	return 0;}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:39,


示例11: cdc_do_config

/* * We _always_ have both CDC ECM and CDC ACM functions. */static int __init cdc_do_config(struct usb_configuration *c){	int	status;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	f_ecm = usb_get_function(fi_ecm);	if (IS_ERR(f_ecm)) {		status = PTR_ERR(f_ecm);		goto err_get_ecm;	}	status = usb_add_function(c, f_ecm);	if (status)		goto err_add_ecm;	f_acm = usb_get_function(fi_serial);	if (IS_ERR(f_acm)) {		status = PTR_ERR(f_acm);		goto err_get_acm;	}	status = usb_add_function(c, f_acm);	if (status)		goto err_add_acm;	return 0;err_add_acm:	usb_put_function(f_acm);err_get_acm:	usb_remove_function(c, f_ecm);err_add_ecm:	usb_put_function(f_ecm);err_get_ecm:	return status;}
开发者ID:mikuhatsune001,项目名称:linux2.6.32,代码行数:42,


示例12: hidg_bind_config

int hidg_bind_config(struct usb_configuration *c,                     struct hidg_func_descriptor *fdesc, int index){    struct f_hidg *hidg;    int status;    if (index >= minors)        return -ENOENT;    /* maybe allocate device-global string IDs, and patch descriptors */    if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {        status = usb_string_id(c->cdev);        if (status < 0)            return status;        ct_func_string_defs[CT_FUNC_HID_IDX].id = status;        hidg_interface_desc.iInterface = status;    }    /* allocate and initialize one new instance */    hidg = kzalloc(sizeof *hidg, GFP_KERNEL);    if (!hidg)        return -ENOMEM;    hidg->minor = index;    hidg->bInterfaceSubClass = fdesc->subclass;    hidg->bInterfaceProtocol = fdesc->protocol;    hidg->report_length = fdesc->report_length;    hidg->report_desc_length = fdesc->report_desc_length;    hidg->report_desc = kmemdup(fdesc->report_desc,                                fdesc->report_desc_length,                                GFP_KERNEL);    if (!hidg->report_desc) {        kfree(hidg);        return -ENOMEM;    }    hidg->func.name    = "hid";    hidg->func.strings = ct_func_strings;    hidg->func.bind    = hidg_bind;    hidg->func.unbind  = hidg_unbind;    hidg->func.set_alt = hidg_set_alt;    hidg->func.disable = hidg_disable;    hidg->func.setup   = hidg_setup;    status = usb_add_function(c, &hidg->func);    if (status)        kfree(hidg);    return status;}
开发者ID:acuicultor,项目名称:Radioactive-kernel,代码行数:50,


示例13: midi_bind_config

static int midi_bind_config(struct usb_configuration *c){    int status;    f_midi = usb_get_function(fi_midi);    if (IS_ERR(f_midi))        return PTR_ERR(f_midi);    status = usb_add_function(c, f_midi);    if (status < 0) {        usb_put_function(f_midi);        return status;    }    return 0;}
开发者ID:mhei,项目名称:linux,代码行数:16,


示例14: tcm_do_config

static int tcm_do_config(struct usb_configuration *c){	int status;	f_tcm = usb_get_function(fi_tcm);	if (IS_ERR(f_tcm))		return PTR_ERR(f_tcm);	status = usb_add_function(c, f_tcm);	if (status < 0) {		usb_put_function(f_tcm);		return status;	}	return 0;}
开发者ID:AlexShiLucky,项目名称:linux,代码行数:16,


示例15: serial_register_ports

static int serial_register_ports(struct usb_composite_dev *cdev,		struct usb_configuration *c, const char *f_name){	int i;	int ret;	ret = usb_add_config_only(cdev, c);	if (ret)		goto out;	for (i = 0; i < n_ports; i++) {		fi_serial[i] = usb_get_function_instance(f_name);		if (IS_ERR(fi_serial[i])) {			ret = PTR_ERR(fi_serial[i]);			goto fail;		}		f_serial[i] = usb_get_function(fi_serial[i]);		if (IS_ERR(f_serial[i])) {			ret = PTR_ERR(f_serial[i]);			goto err_get_func;		}		ret = usb_add_function(c, f_serial[i]);		if (ret)			goto err_add_func;	}	return 0;err_add_func:	usb_put_function(f_serial[i]);err_get_func:	usb_put_function_instance(fi_serial[i]);fail:	i--;	while (i >= 0) {		usb_remove_function(c, f_serial[i]);		usb_put_function(f_serial[i]);		usb_put_function_instance(fi_serial[i]);		i--;	}out:	return ret;}
开发者ID:lixuhui112,项目名称:myimx6-linux,代码行数:47,


示例16: mtp_bind_config

int mtp_bind_config(struct usb_configuration *c){	int ret = 0;	int status;	printk(KERN_INFO "Gadget Usb: mtp_bind_config/n");	init_waitqueue_head(&g_usb_mtp_context.rx_wq);	init_waitqueue_head(&g_usb_mtp_context.tx_wq);	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);	status = usb_string_id(c->cdev);	if (status >= 0) {		mtp_string_defs1[STRING_INTERFACE].id = status;		intf_desc.iInterface = status;	}	mtp_string_defs2[STRING_MTP].id = mtp_ext_str_idx;	g_usb_mtp_context.cdev = c->cdev;	g_usb_mtp_context.function.name = "mtp";	g_usb_mtp_context.function.descriptors = fs_mtp_descs;	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;	g_usb_mtp_context.function.strings = mtp_strings;	g_usb_mtp_context.function.bind = mtp_function_bind;	g_usb_mtp_context.function.unbind = mtp_function_unbind;	g_usb_mtp_context.function.setup = mtp_function_setup;	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;	g_usb_mtp_context.function.disable = mtp_function_disable;	/* start disabled */	g_usb_mtp_context.function.hidden = 1;	ret = usb_add_function(c, &g_usb_mtp_context.function);	if (ret) {		mtp_err("MTP gadget driver failed to initialize/n");		return ret;	}	return 0;}
开发者ID:atarii,项目名称:BDA-ACTV,代码行数:47,


示例17: rockusb_add

static int rockusb_add(struct usb_configuration *c){	struct f_rockusb *f_rkusb = get_rkusb();	int status;	debug("%s: cdev: 0x%p/n", __func__, c->cdev);	f_rkusb->usb_function.name = "f_rockusb";	f_rkusb->usb_function.bind = rockusb_bind;	f_rkusb->usb_function.unbind = rockusb_unbind;	f_rkusb->usb_function.set_alt = rockusb_set_alt;	f_rkusb->usb_function.disable = rockusb_disable;	f_rkusb->usb_function.strings = rkusb_strings;	status = usb_add_function(c, &f_rkusb->usb_function);	if (status) {		free(f_rkusb);		rockusb_func = f_rkusb;	}	return status;}
开发者ID:axxia,项目名称:axxia_u-boot,代码行数:21,


示例18: acm_ms_do_config

/* * We _always_ have both ACM and mass storage functions. */static int __init acm_ms_do_config(struct usb_configuration *c){	struct f_serial_opts *opts;	int	status;	if (gadget_is_otg(c->cdev->gadget)) {		c->descriptors = otg_desc;		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	f_acm_inst = usb_get_function_instance("acm");	if (IS_ERR(f_acm_inst))		return PTR_ERR(f_acm_inst);	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);	opts->port_num = tty_line;	f_acm = usb_get_function(f_acm_inst);	if (IS_ERR(f_acm)) {		status = PTR_ERR(f_acm);		goto err_func;	}	status = usb_add_function(c, f_acm);	if (status < 0)		goto err_conf;	status = fsg_bind_config(c->cdev, c, &fsg_common);	if (status < 0)		goto err_fsg;	return 0;err_fsg:	usb_remove_function(c, f_acm);err_conf:	usb_put_function(f_acm);err_func:	usb_put_function_instance(f_acm_inst);	return status;}
开发者ID:AiWinters,项目名称:linux,代码行数:43,


示例19: rawbulk_bind_config

int rawbulk_bind_config(struct usb_configuration *c, int transfer_id) {    int rc;       struct rawbulk_function *fn = rawbulk_lookup_function(transfer_id);    if (!fn)        return -ENOMEM;            printk(KERN_INFO "add %s to config./n", fn->longname);    if (fn->string_defs[0].id == 0) {        rc = usb_string_id(c->cdev);        if (rc < 0)            return rc;        fn->string_defs[0].id = rc;        fn->interface.iInterface = rc;    }    if (!fn->initialized) {        fn->function.name = fn->longname;        fn->function.setup = rawbulk_function_setup;        fn->function.bind = rawbulk_function_bind;        fn->function.unbind = rawbulk_function_unbind;        fn->function.set_alt = rawbulk_function_setalt;        fn->function.disable = rawbulk_function_disable;        INIT_WORK(&fn->activator, do_activate);        /*if(fn->transfer_id == RAWBULK_TID_MODEM) {            INIT_WORK(&flow_control, modem_flow_control);            INIT_WORK(&dtr_status, dtr_status_query);        }*/             fn->initialized = 1;    }    rc = usb_add_function(c, &fn->function);    if (rc < 0)        printk(KERN_ERR "%s - failed to config %d./n", __func__, rc);    return rc;}
开发者ID:Elnter,项目名称:j608_kernel,代码行数:40,


示例20: rndis_bind_config_vendor

intrndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],                         u32 vendorID, const char *manufacturer, struct eth_dev *dev){    struct f_rndis	*rndis;    int		status;    if (!can_support_rndis(c) || !ethaddr)        return -EINVAL;    /* setup RNDIS itself */    status = rndis_init();    if (status < 0)        return status;    if (rndis_string_defs[0].id == 0) {        status = usb_string_ids_tab(c->cdev, rndis_string_defs);        if (status)            return status;        rndis_control_intf.iInterface = rndis_string_defs[0].id;        rndis_data_intf.iInterface = rndis_string_defs[1].id;        rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;    }    /* allocate and initialize one new instance */    status = -ENOMEM;    rndis = kzalloc(sizeof *rndis, GFP_KERNEL);    if (!rndis)        goto fail;    __rndis = rndis;    memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);    rndis->vendorID = vendorID;    rndis->manufacturer = manufacturer;    rndis->port.ioport = dev;    /* RNDIS activates when the host changes this filter */    rndis->port.cdc_filter = 0;    /* RNDIS has special (and complex) framing */    rndis->port.header_len = sizeof(struct rndis_packet_msg_type);    rndis->port.wrap = rndis_add_header;    rndis->port.unwrap = rndis_rm_hdr;    rndis->port.ul_max_pkts_per_xfer = rndis_ul_max_pkt_per_xfer;    rndis->port.dl_max_pkts_per_xfer = rndis_dl_max_pkt_per_xfer;    rndis->port.rx_trigger_enabled = rx_trigger_enabled;    rndis->port.func.name = "rndis";    rndis->port.func.strings = rndis_strings;    /* descriptors are per-instance copies */    rndis->port.func.bind = rndis_bind;    rndis->port.func.unbind = rndis_unbind;    rndis->port.func.set_alt = rndis_set_alt;    rndis->port.func.setup = rndis_setup;    rndis->port.func.disable = rndis_disable;    status = usb_add_function(c, &rndis->port.func);    if (status) {        kfree(rndis);fail:        rndis_exit();    }    return status;}
开发者ID:Clumsy-Kernel-Development,项目名称:M9_Kernel,代码行数:66,


示例21: zero_bind

static int zero_bind(struct usb_composite_dev *cdev){	struct f_ss_opts	*ss_opts;	struct f_lb_opts	*lb_opts;	int			status;	/* Allocate string descriptor numbers ... note that string	 * contents can be overridden by the composite_dev glue.	 */	status = usb_string_ids_tab(cdev, strings_dev);	if (status < 0)		return status;	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;	device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id;	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);	func_inst_ss = usb_get_function_instance("SourceSink");	if (IS_ERR(func_inst_ss))		return PTR_ERR(func_inst_ss);	ss_opts =  container_of(func_inst_ss, struct f_ss_opts, func_inst);	ss_opts->pattern = gzero_options.pattern;	ss_opts->isoc_interval = gzero_options.isoc_interval;	ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;	ss_opts->isoc_mult = gzero_options.isoc_mult;	ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;	ss_opts->bulk_buflen = gzero_options.bulk_buflen;	func_ss = usb_get_function(func_inst_ss);	if (IS_ERR(func_ss)) {		status = PTR_ERR(func_ss);		goto err_put_func_inst_ss;	}	func_inst_lb = usb_get_function_instance("Loopback");	if (IS_ERR(func_inst_lb)) {		status = PTR_ERR(func_inst_lb);		goto err_put_func_ss;	}	lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);	lb_opts->bulk_buflen = gzero_options.bulk_buflen;	lb_opts->qlen = gzero_options.qlen;	func_lb = usb_get_function(func_inst_lb);	if (IS_ERR(func_lb)) {		status = PTR_ERR(func_lb);		goto err_put_func_inst_lb;	}	sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;	loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;	/* support autoresume for remote wakeup testing */	sourcesink_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;	loopback_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;	sourcesink_driver.descriptors = NULL;	loopback_driver.descriptors = NULL;	if (autoresume) {		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		autoresume_step_ms = autoresume * 1000;	}	/* support OTG systems */	if (gadget_is_otg(cdev->gadget)) {		if (!otg_desc[0]) {			struct usb_descriptor_header *usb_desc;			usb_desc = usb_otg_descriptor_alloc(cdev->gadget);			if (!usb_desc) {				status = -ENOMEM;				goto err_conf_flb;			}			usb_otg_descriptor_init(cdev->gadget, usb_desc);			otg_desc[0] = usb_desc;			otg_desc[1] = NULL;		}		sourcesink_driver.descriptors = otg_desc;		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		loopback_driver.descriptors = otg_desc;		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	/* Register primary, then secondary configuration.  Note that	 * SH3 only allows one config...	 */	if (loopdefault) {		usb_add_config_only(cdev, &loopback_driver);		usb_add_config_only(cdev, &sourcesink_driver);	} else {		usb_add_config_only(cdev, &sourcesink_driver);		usb_add_config_only(cdev, &loopback_driver);	}	status = usb_add_function(&sourcesink_driver, func_ss);	if (status)		goto err_free_otg_desc;//.........这里部分代码省略.........
开发者ID:Chong-Li,项目名称:cse522,代码行数:101,


示例22: uvc_bind_config

/** * uvc_bind_config - add a UVC function to a configuration * @c: the configuration to support the UVC instance * Context: single threaded during gadget setup * * Returns zero on success, else negative errno. * * Caller must have called @uvc_setup(). Caller is also responsible for * calling @uvc_cleanup() before module unload. */int __inituvc_bind_config(struct usb_configuration *c,		const struct uvc_descriptor_header * const *control,		const struct uvc_descriptor_header * const *fs_streaming,		const struct uvc_descriptor_header * const *hs_streaming){	struct uvc_device *uvc;	int ret = 0;	/* TODO Check if the USB device controller supports the required	 * features.	 */	if (!gadget_is_dualspeed(c->cdev->gadget))		return -EINVAL;	uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);	if (uvc == NULL)		return -ENOMEM;	uvc->state = UVC_STATE_DISCONNECTED;	/* Validate the descriptors. */	if (control == NULL || control[0] == NULL ||	    control[0]->bDescriptorSubType != UVC_VC_HEADER)		goto error;	if (fs_streaming == NULL || fs_streaming[0] == NULL ||	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)		goto error;	if (hs_streaming == NULL || hs_streaming[0] == NULL ||	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)		goto error;	uvc->desc.control = control;	uvc->desc.fs_streaming = fs_streaming;	uvc->desc.hs_streaming = hs_streaming;	/* Allocate string descriptor numbers. */	if ((ret = usb_string_id(c->cdev)) < 0)		goto error;	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;	uvc_iad.iFunction = ret;	if ((ret = usb_string_id(c->cdev)) < 0)		goto error;	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;	uvc_control_intf.iInterface = ret;	if ((ret = usb_string_id(c->cdev)) < 0)		goto error;	uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;	uvc_streaming_intf_alt0.iInterface = ret;	uvc_streaming_intf_alt1.iInterface = ret;	/* Register the function. */	uvc->func.name = "uvc";	uvc->func.strings = uvc_function_strings;	uvc->func.bind = uvc_function_bind;	uvc->func.unbind = uvc_function_unbind;	uvc->func.get_alt = uvc_function_get_alt;	uvc->func.set_alt = uvc_function_set_alt;	uvc->func.disable = uvc_function_disable;	uvc->func.setup = uvc_function_setup;	ret = usb_add_function(c, &uvc->func);	if (ret)		kfree(uvc);	return 0;error:	kfree(uvc);	return ret;}
开发者ID:3sOx,项目名称:asuswrt-merlin,代码行数:85,


示例23: ecm_bind_config

/** * ecm_bind_config - add CDC Ethernet network link to a configuration * @c: the configuration to support the network link * @ethaddr: a buffer in which the ethernet address of the host side *	side of the link was recorded * Context: single threaded during gadget setup * * Returns zero on success, else negative errno. * * Caller must have called @gether_setup().  Caller is also responsible * for calling @gether_cleanup() before module unload. */intecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]){	struct f_ecm	*ecm;	int		status;		if (!can_support_ecm(c->cdev->gadget) || !ethaddr)		return -EINVAL;	/* maybe allocate device-global string IDs */	if (ecm_string_defs[0].id == 0) {		/* control interface label */		status = 5;		if (status < 0)			return status;		ecm_string_defs[0].id = status;		ecm_control_intf.iInterface = status;#ifdef CONFIG_LGE_USB_GADGET_DRIVER		/* MAC address */		status = usb_string_id(c->cdev);		if (status < 0)			return status;		ecm_string_defs[1].id = status;		pr_info("%s: iMACAddress = %d/n", __func__, status);		ecm_desc.iMACAddress = status;#endif		/* data interface label */		status = usb_string_id(c->cdev);		if (status < 0)			return status;		ecm_string_defs[2].id = status;		ecm_data_intf.iInterface = status;/* NOTE : if NOT defined */#ifndef CONFIG_LGE_USB_GADGET_DRIVER		/* MAC address */		status = usb_string_id(c->cdev);		if (status < 0)			return status;		ecm_string_defs[1].id = status;		ecm_desc.iMACAddress = status;#endif	}	/* allocate and initialize one new instance */	ecm = kzalloc(sizeof *ecm, GFP_KERNEL);	if (!ecm)		return -ENOMEM;	/* export host's Ethernet address in CDC format */	snprintf(ecm->ethaddr, sizeof ecm->ethaddr,		"%02X%02X%02X%02X%02X%02X",		ethaddr[0], ethaddr[1], ethaddr[2],		ethaddr[3], ethaddr[4], ethaddr[5]);	ecm_string_defs[1].s = ecm->ethaddr;	ecm->port.cdc_filter = DEFAULT_FILTER;#ifdef CONFIG_LGE_USB_GADGET_DRIVER        ecm->port.func.name = "ecm";#else	ecm->port.func.name = "cdc_ethernet";#endif	ecm->port.func.strings = ecm_strings;	/* descriptors are per-instance copies */	ecm->port.func.bind = ecm_bind;	ecm->port.func.unbind = ecm_unbind;	ecm->port.func.set_alt = ecm_set_alt;	ecm->port.func.get_alt = ecm_get_alt;	ecm->port.func.setup = ecm_setup;	ecm->port.func.disable = ecm_disable;	ecm->port.func.suspend = ecm_suspend;	ecm->port.func.resume  = ecm_resume;	status = usb_add_function(c, &ecm->port.func);	if (status) {		ecm_string_defs[1].s = NULL;		kfree(ecm);	}	return status;}
开发者ID:ARMP,项目名称:android_kernel_lge_x3,代码行数:98,


示例24: mtp_function_add

int  mtp_function_add(struct usb_composite_dev *cdev,	struct usb_configuration *c)#endif{	int ret = 0;	int status;	init_waitqueue_head(&g_usb_mtp_context.rx_wq);	init_waitqueue_head(&g_usb_mtp_context.tx_wq);	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);	status = usb_string_id(c->cdev);	if (status >= 0) {		mtp_string_defs[STRING_INTERFACE].id = status;        intf_desc.iInterface = status;	}	mtp_string_defs[STRING_MTP].id = mtp_ext_str_idx;#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT    g_usb_mtp_context.cdev = c->cdev;#else	g_usb_mtp_context.cdev = cdev;#endif	g_usb_mtp_context.function.name = "mtp";	g_usb_mtp_context.function.descriptors = fs_mtp_descs;	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;	g_usb_mtp_context.function.strings = mtp_strings;	g_usb_mtp_context.function.bind = mtp_function_bind;	g_usb_mtp_context.function.unbind = mtp_function_unbind;	g_usb_mtp_context.function.setup = mtp_function_setup;	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;	g_usb_mtp_context.function.disable = mtp_function_disable;#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT	ret = mtp_function_init();	if (ret)		goto mtp_exit;	ret = misc_register(&mtp_enable_device);	if (ret)		goto misc_deregister;#endif#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT	/* start disabled */	g_usb_mtp_context.function.disabled = 1;#endif	ret = usb_add_function(c, &g_usb_mtp_context.function);	if (ret) {		mtp_err("MTP gadget driver failed to initialize/n");		return ret;	}	return 0;#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INITmtp_misc_deregister:	misc_deregister(&mtp_enable_device);mtp_exit:	mtp_function_exit();	return ret;#endif}
开发者ID:LDrifta,项目名称:Kernel_MS910_ZVD_Speed_Unlshd,代码行数:73,


示例25: nokia_bind_config

static int __init nokia_bind_config(struct usb_configuration *c){	struct usb_function *f_acm;	struct usb_function *f_phonet = NULL;	struct usb_function *f_obex1 = NULL;	struct usb_function *f_ecm;	struct usb_function *f_obex2 = NULL;	int status = 0;	int obex1_stat = -1;	int obex2_stat = -1;	int phonet_stat = -1;	if (!IS_ERR(fi_phonet)) {		f_phonet = usb_get_function(fi_phonet);		if (IS_ERR(f_phonet))			pr_debug("could not get phonet function/n");	}	if (!IS_ERR(fi_obex1)) {		f_obex1 = usb_get_function(fi_obex1);		if (IS_ERR(f_obex1))			pr_debug("could not get obex function 0/n");	}	if (!IS_ERR(fi_obex2)) {		f_obex2 = usb_get_function(fi_obex2);		if (IS_ERR(f_obex2))			pr_debug("could not get obex function 1/n");	}	f_acm = usb_get_function(fi_acm);	if (IS_ERR(f_acm)) {		status = PTR_ERR(f_acm);		goto err_get_acm;	}	f_ecm = usb_get_function(fi_ecm);	if (IS_ERR(f_ecm)) {		status = PTR_ERR(f_ecm);		goto err_get_ecm;	}	if (!IS_ERR_OR_NULL(f_phonet)) {		phonet_stat = usb_add_function(c, f_phonet);		if (phonet_stat)			pr_debug("could not add phonet function/n");	}	if (!IS_ERR_OR_NULL(f_obex1)) {		obex1_stat = usb_add_function(c, f_obex1);		if (obex1_stat)			pr_debug("could not add obex function 0/n");	}	if (!IS_ERR_OR_NULL(f_obex2)) {		obex2_stat = usb_add_function(c, f_obex2);		if (obex2_stat)			pr_debug("could not add obex function 1/n");	}	status = usb_add_function(c, f_acm);	if (status)		goto err_conf;	status = usb_add_function(c, f_ecm);	if (status) {		pr_debug("could not bind ecm config %d/n", status);		goto err_ecm;	}	if (c == &nokia_config_500ma_driver) {		f_acm_cfg1 = f_acm;		f_ecm_cfg1 = f_ecm;		f_phonet_cfg1 = f_phonet;		f_obex1_cfg1 = f_obex1;		f_obex2_cfg1 = f_obex2;	} else {		f_acm_cfg2 = f_acm;		f_ecm_cfg2 = f_ecm;		f_phonet_cfg2 = f_phonet;		f_obex1_cfg2 = f_obex1;		f_obex2_cfg2 = f_obex2;	}	return status;err_ecm:	usb_remove_function(c, f_acm);err_conf:	if (!obex2_stat)		usb_remove_function(c, f_obex2);	if (!obex1_stat)		usb_remove_function(c, f_obex1);	if (!phonet_stat)		usb_remove_function(c, f_phonet);	usb_put_function(f_ecm);err_get_ecm:	usb_put_function(f_acm);err_get_acm:	if (!IS_ERR_OR_NULL(f_obex2))		usb_put_function(f_obex2);	if (!IS_ERR_OR_NULL(f_obex1))//.........这里部分代码省略.........
开发者ID:7799,项目名称:linux,代码行数:101,


示例26: gser_bind_config

//.........这里部分代码省略.........			gser_string_defs[0].id = status;		}	}#endif	if (modem_string_defs[0].id == 0 &&			p->func_type == USB_FSER_FUNC_MODEM) {		status = usb_string_id(c->cdev);		if (status < 0) {			printk(KERN_ERR "%s: return %d/n", __func__, status);			return status;		}		modem_string_defs[0].id = status;	}	if (modem_string_defs[1].id == 0 &&			p->func_type == USB_FSER_FUNC_MODEM_MDM) {		status = usb_string_id(c->cdev);		if (status < 0) {			printk(KERN_ERR "%s: return %d/n", __func__, status);			return status;		}		modem_string_defs[1].id = status;	}	if (gser_string_defs[0].id == 0 &&			(p->func_type == USB_FSER_FUNC_SERIAL			|| p->func_type == USB_FSER_FUNC_AUTOBOT)) {		status = usb_string_id(c->cdev);		if (status < 0) {			printk(KERN_ERR "%s: return %d/n", __func__, status);			return status;		}		gser_string_defs[0].id = status;	}	/* allocate and initialize one new instance */	gser = kzalloc(sizeof *gser, GFP_KERNEL);	if (!gser)		return -ENOMEM;#ifdef CONFIG_MODEM_SUPPORT	spin_lock_init(&gser->lock);#endif	gser->port_num = port_num;	gser->port.func.name = "gser";	gser->port.func.strings = gser_strings;	gser->port.func.bind = gser_bind;	gser->port.func.unbind = gser_unbind;	gser->port.func.set_alt = gser_set_alt;	gser->port.func.disable = gser_disable;	gser->transport		= gserial_ports[port_num].transport;#ifdef CONFIG_MODEM_SUPPORT	/* We support only two ports for now */	if (port_num == 0) {		gser->port.func.name = "modem";	} else		gser->port.func.name = "nmea";	gser->port.func.setup = gser_setup;	gser->port.connect = gser_connect;	gser->port.get_dtr = gser_get_dtr;	gser->port.get_rts = gser_get_rts;	gser->port.send_carrier_detect = gser_send_carrier_detect;	gser->port.send_ring_indicator = gser_send_ring_indicator;	gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;	gser->port.disconnect = gser_disconnect;	gser->port.send_break = gser_send_break;#endif	switch (p->func_type) {	case USB_FSER_FUNC_MODEM:		gser->port.func.name = "modem";		gser->port.func.strings = modem_strings;		gser_interface_desc.iInterface = modem_string_defs[0].id;		break;	case USB_FSER_FUNC_MODEM_MDM:		gser->port.func.name = "modem_mdm";		gser->port.func.strings = modem_strings;		gser_interface_desc.iInterface = modem_string_defs[1].id;		break;	case USB_FSER_FUNC_SERIAL:	case USB_FSER_FUNC_AUTOBOT:		gser->port.func.name = "serial";		gser->port.func.strings = gser_strings;		gser_interface_desc.iInterface = gser_string_defs[0].id;		break;	case USB_FSER_FUNC_NONE:	default	:		break;	}	status = usb_add_function(c, &gser->port.func);	if (status)		kfree(gser);	return status;}
开发者ID:Flemmard,项目名称:htc7x30-3.0,代码行数:101,


示例27: uvc_bind_config

/** * uvc_bind_config - add a UVC function to a configuration * @c: the configuration to support the UVC instance * Context: single threaded during gadget setup * * Returns zero on success, else negative errno. * * Caller must have called @uvc_setup(). Caller is also responsible for * calling @uvc_cleanup() before module unload. */int __inituvc_bind_config(struct usb_configuration *c,		const struct uvc_descriptor_header * const *fs_control,		const struct uvc_descriptor_header * const *ss_control,		const struct uvc_descriptor_header * const *fs_streaming,		const struct uvc_descriptor_header * const *hs_streaming,		const struct uvc_descriptor_header * const *ss_streaming){	struct uvc_device *uvc;	int ret = 0;	/* TODO Check if the USB device controller supports the required	 * features.	 */	if (!gadget_is_dualspeed(c->cdev->gadget))		return -EINVAL;	uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);	if (uvc == NULL)		return -ENOMEM;	uvc->state = UVC_STATE_DISCONNECTED;	/* Validate the descriptors. */	if (fs_control == NULL || fs_control[0] == NULL ||	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)		goto error;	if (ss_control == NULL || ss_control[0] == NULL ||	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)		goto error;	if (fs_streaming == NULL || fs_streaming[0] == NULL ||	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)		goto error;	if (hs_streaming == NULL || hs_streaming[0] == NULL ||	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)		goto error;	if (ss_streaming == NULL || ss_streaming[0] == NULL ||	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)		goto error;	uvc->desc.fs_control = fs_control;	uvc->desc.ss_control = ss_control;	uvc->desc.fs_streaming = fs_streaming;	uvc->desc.hs_streaming = hs_streaming;	uvc->desc.ss_streaming = ss_streaming;	/* String descriptors are global, we only need to allocate string IDs	 * for the first UVC function. UVC functions beyond the first (if any)	 * will reuse the same IDs.	 */	if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);		if (ret)			goto error;		uvc_iad.iFunction =			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;		uvc_control_intf.iInterface =			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;		uvc_streaming_intf_alt0.iInterface = ret;		uvc_streaming_intf_alt1.iInterface = ret;	}	/* Register the function. */	uvc->func.name = "uvc";	uvc->func.strings = uvc_function_strings;	uvc->func.bind = uvc_function_bind;	uvc->func.unbind = uvc_function_unbind;	uvc->func.get_alt = uvc_function_get_alt;	uvc->func.set_alt = uvc_function_set_alt;	uvc->func.disable = uvc_function_disable;	uvc->func.setup = uvc_function_setup;	ret = usb_add_function(c, &uvc->func);	if (ret)		kfree(uvc);	return ret;error:	kfree(uvc);	return ret;}
开发者ID:7799,项目名称:linux,代码行数:97,



注:本文中的usb_add_function函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


C++ usb_add_hcd函数代码示例
C++ usbStart函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。