Ejemplo n.º 1
0
/**
 * Probe device
 *
 * @v func		USB function
 * @v config		Configuration descriptor
 * @ret rc		Return status code
 */
static int acm_probe ( struct usb_function *func,
		       struct usb_configuration_descriptor *config ) {
	struct usb_device *usb = func->usb;
	struct rndis_device *rndis;
	struct acm_device *acm;
	int rc;

	/* Allocate and initialise structure */
	rndis = alloc_rndis ( sizeof ( *acm ) );
	if ( ! rndis ) {
		rc = -ENOMEM;
		goto err_alloc;
	}
	rndis_init ( rndis, &acm_operations );
	rndis->netdev->dev = &func->dev;
	acm = rndis->priv;
	acm->usb = usb;
	acm->bus = usb->port->hub->bus;
	acm->rndis = rndis;
	usbnet_init ( &acm->usbnet, func, &acm_intr_operations,
		      &acm_in_operations, &acm_out_operations );
	usb_refill_init ( &acm->usbnet.intr, 0, ACM_INTR_MAX_FILL );
	usb_refill_init ( &acm->usbnet.in, ACM_IN_MTU, ACM_IN_MAX_FILL );

	/* Describe USB network device */
	if ( ( rc = usbnet_describe ( &acm->usbnet, config ) ) != 0 ) {
		DBGC ( acm, "ACM %p could not describe: %s\n",
		       acm, strerror ( rc ) );
		goto err_describe;
	}

	/* Register RNDIS device */
	if ( ( rc = register_rndis ( rndis ) ) != 0 )
		goto err_register;

	usb_func_set_drvdata ( func, acm );
	return 0;

	unregister_rndis ( rndis );
 err_register:
 err_describe:
	free_rndis ( rndis );
 err_alloc:
	return rc;
}
Ejemplo n.º 2
0
int
rndis_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;
}