Exemple #1
0
static ssize_t value_store(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{
	u16 val;
	u16 reg_addr;
	const char *name = attr->attr.name;
	struct most_dci_obj *dci_obj = to_dci_obj(dev);
	struct usb_device *usb_dev = dci_obj->usb_device;
	int err = kstrtou16(buf, 16, &val);

	if (err)
		return err;

	if (!strcmp(name, "arb_address")) {
		dci_obj->reg_addr = val;
		return count;
	}

	if (!strcmp(name, "arb_value"))
		err = drci_wr_reg(usb_dev, dci_obj->reg_addr, val);
	else if (!strcmp(name, "sync_ep"))
		err = start_sync_ep(usb_dev, val);
	else if (!get_static_reg_addr(rw_regs, name, &reg_addr))
		err = drci_wr_reg(usb_dev, reg_addr, val);
	else
		return -EFAULT;

	if (err < 0)
		return err;

	return count;
}
Exemple #2
0
static ssize_t store_value(struct most_dci_obj *dci_obj,
			   struct most_dci_attribute *attr,
			   const char *buf, size_t count)
{
	u16 val;
	u16 reg_addr;
	const char *name = attr->attr.name;
	int err = kstrtou16(buf, 16, &val);

	if (err)
		return err;

	if (!strcmp(name, "arb_address")) {
		dci_obj->reg_addr = val;
		return count;
	}

	if (!strcmp(name, "arb_value")) {
		reg_addr = dci_obj->reg_addr;
	} else if (!strcmp(name, "sync_ep")) {
		u16 ep = val;

		reg_addr = DRCI_REG_BASE + DRCI_COMMAND + ep * 16;
		val = 1;
	} else if (get_static_reg_addr(ro_regs, name, &reg_addr)) {
		return -EFAULT;
	}

	err = drci_wr_reg(dci_obj->usb_device, reg_addr, val);
	if (err < 0)
		return err;

	return count;
}
Exemple #3
0
/**
 * hdm_probe - probe function of USB device driver
 * @interface: Interface of the attached USB device
 * @id: Pointer to the USB ID table.
 *
 * This allocates and initializes the device instance, adds the new
 * entry to the internal list, scans the USB descriptors and registers
 * the interface with the core.
 * Additionally, the DCI objects are created and the hardware is sync'd.
 *
 * Return 0 on success. In case of an error a negative number is returned.
 */
static int
hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
	struct usb_host_interface *usb_iface_desc = interface->cur_altsetting;
	struct usb_device *usb_dev = interface_to_usbdev(interface);
	struct device *dev = &usb_dev->dev;
	struct most_dev *mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
	unsigned int i;
	unsigned int num_endpoints;
	struct most_channel_capability *tmp_cap;
	struct usb_endpoint_descriptor *ep_desc;
	int ret = 0;
	int err;

	if (!mdev)
		goto exit_ENOMEM;

	usb_set_intfdata(interface, mdev);
	num_endpoints = usb_iface_desc->desc.bNumEndpoints;
	mutex_init(&mdev->io_mutex);
	INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
	setup_timer(&mdev->link_stat_timer, link_stat_timer_handler,
		    (unsigned long)mdev);

	mdev->usb_device = usb_dev;
	mdev->link_stat_timer.expires = jiffies + (2 * HZ);

	mdev->iface.mod = hdm_usb_fops.owner;
	mdev->iface.interface = ITYPE_USB;
	mdev->iface.configure = hdm_configure_channel;
	mdev->iface.request_netinfo = hdm_request_netinfo;
	mdev->iface.enqueue = hdm_enqueue;
	mdev->iface.poison_channel = hdm_poison_channel;
	mdev->iface.description = mdev->description;
	mdev->iface.num_channels = num_endpoints;

	snprintf(mdev->description, sizeof(mdev->description),
		 "usb_device %d-%s:%d.%d",
		 usb_dev->bus->busnum,
		 usb_dev->devpath,
		 usb_dev->config->desc.bConfigurationValue,
		 usb_iface_desc->desc.bInterfaceNumber);

	mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
	if (!mdev->conf)
		goto exit_free;

	mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
	if (!mdev->cap)
		goto exit_free1;

	mdev->iface.channel_vector = mdev->cap;
	mdev->iface.priv = NULL;

	mdev->ep_address =
		kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
	if (!mdev->ep_address)
		goto exit_free2;

	mdev->busy_urbs =
		kcalloc(num_endpoints, sizeof(*mdev->busy_urbs), GFP_KERNEL);
	if (!mdev->busy_urbs)
		goto exit_free3;

	tmp_cap = mdev->cap;
	for (i = 0; i < num_endpoints; i++) {
		ep_desc = &usb_iface_desc->endpoint[i].desc;
		mdev->ep_address[i] = ep_desc->bEndpointAddress;
		mdev->padding_active[i] = false;
		mdev->is_channel_healthy[i] = true;

		snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
			 mdev->ep_address[i]);

		tmp_cap->name_suffix = &mdev->suffix[i][0];
		tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
		tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
		tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
		tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
		tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
				     MOST_CH_ISOC | MOST_CH_SYNC;
		if (usb_endpoint_dir_in(ep_desc))
			tmp_cap->direction = MOST_CH_RX;
		else
			tmp_cap->direction = MOST_CH_TX;
		tmp_cap++;
		init_usb_anchor(&mdev->busy_urbs[i]);
		spin_lock_init(&mdev->channel_lock[i]);
		err = drci_wr_reg(usb_dev,
				  DRCI_REG_BASE + DRCI_COMMAND +
				  ep_desc->bEndpointAddress * 16,
				  1);
		if (err < 0)
			dev_warn(dev, "DCI Sync for EP %02x failed",
				 ep_desc->bEndpointAddress);
	}
	dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
		   le16_to_cpu(usb_dev->descriptor.idVendor),
		   le16_to_cpu(usb_dev->descriptor.idProduct),
		   usb_dev->bus->busnum,
		   usb_dev->devnum);

	dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
		   usb_dev->bus->busnum,
		   usb_dev->devpath,
		   usb_dev->config->desc.bConfigurationValue,
		   usb_iface_desc->desc.bInterfaceNumber);

	mdev->parent = most_register_interface(&mdev->iface);
	if (IS_ERR(mdev->parent)) {
		ret = PTR_ERR(mdev->parent);
		goto exit_free4;
	}

	mutex_lock(&mdev->io_mutex);
	if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
	    le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
		/* this increments the reference count of the instance
		 * object of the core
		 */
		mdev->dci = create_most_dci_obj(mdev->parent);
		if (!mdev->dci) {
			mutex_unlock(&mdev->io_mutex);
			most_deregister_interface(&mdev->iface);
			ret = -ENOMEM;
			goto exit_free4;
		}

		kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
		mdev->dci->usb_device = mdev->usb_device;
	}
	mutex_unlock(&mdev->io_mutex);
	return 0;

exit_free4:
	kfree(mdev->busy_urbs);
exit_free3:
	kfree(mdev->ep_address);
exit_free2:
	kfree(mdev->cap);
exit_free1:
	kfree(mdev->conf);
exit_free:
	kfree(mdev);
exit_ENOMEM:
	if (ret == 0 || ret == -ENOMEM) {
		ret = -ENOMEM;
		dev_err(dev, "out of memory\n");
	}
	return ret;
}
Exemple #4
0
static inline int start_sync_ep(struct usb_device *usb_dev, u16 ep)
{
	return drci_wr_reg(usb_dev, DRCI_REG_BASE + DRCI_COMMAND + ep * 16, 1);
}