static int rmidev_init_device(struct rmidev_data *data)
{
	dev_t dev_no;
	int retval;
	struct device *device_ptr;

	if (rmidev_major_num) {
		dev_no = MKDEV(rmidev_major_num, 0);
		retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
	} else {
		retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
		/* let kernel allocate a major for us */
		rmidev_major_num = MAJOR(dev_no);
		dev_info(&data->pdev->dev, "Major number of rmidev: %d\n",
				 rmidev_major_num);
	}
	if (retval < 0) {
		dev_err(&data->pdev->dev,
			"Failed to register or allocate char dev, code %d.\n",
				retval);
		goto exit;
	} else {
		dev_info(&data->pdev->dev, "Allocated rmidev %d %d.\n",
			 MAJOR(dev_no), MINOR(dev_no));
	}

	mutex_init(&data->file_mutex);

	cdev_init(&data->main_dev, &rmidev_fops);

	retval = cdev_add(&data->main_dev, dev_no, 1);
	if (retval) {
		dev_err(&data->pdev->dev, "Error %d adding rmi_char_dev.\n",
			retval);
		rmidev_device_cleanup(data);
		goto exit;
	}

	dev_set_name(&data->pdev->dev, "rmidev%d", MINOR(dev_no));
	data->device_class = rmidev_device_class;
	device_ptr = device_create(
			data->device_class,
			NULL, dev_no, NULL,
			CHAR_DEVICE_NAME"%d",
			MINOR(dev_no));

	if (IS_ERR(device_ptr)) {
		dev_err(&data->pdev->dev,
			"Failed to create rmi device.\n");
		rmidev_device_cleanup(data);
		retval = -ENODEV;
	}
exit:
	return retval;
}
Exemple #2
0
static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data)
{
	struct rmidev_handle *rmidev = rmi4_data->rmidev;
	struct rmidev_data *dev_data = NULL;

	if (!rmidev)
		goto exit;

	sysfs_remove_group(rmidev->attr_dir, &attr_group);

	sysfs_remove_bin_file(rmidev->attr_dir, &attr_data);

	kobject_put(rmidev->attr_dir);

	dev_data = &rmidev->dev_data;
	if (dev_data) {
		rmidev_device_cleanup(dev_data);
		mutex_destroy(&dev_data->file_mutex);
	}

	unregister_chrdev_region(rmidev->dev_no, 1);

	class_destroy(rmidev_device_class);

	kfree(rmidev);
	rmi4_data->rmidev = NULL;

exit:
	return;
}
Exemple #3
0
static void rmidev_remove_device(struct rmi_char_device *cd)
{
	struct rmidev_data *data;

	dev_dbg(&cd->dev, "%s: removing an rmidev device.\n", __func__);
	if (!cd)
		return;

	data = cd->data;
	if (data)
		rmidev_device_cleanup(data);
}
Exemple #4
0
static int rmidev_init_device(struct rmi_char_device *cd)
{
	struct rmi_device *rmi_dev = cd->rmi_dev;
	struct rmidev_data *data;
	dev_t dev_no;
	int retval;
	struct device *device_ptr;

	if (rmidev_major_num) {
		dev_no = MKDEV(rmidev_major_num, cd->rmi_dev->number);
		retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
	} else {
		retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
		/* let kernel allocate a major for us */
		rmidev_major_num = MAJOR(dev_no);
		dev_info(&rmi_dev->dev, "Major number of rmidev: %d\n",
				 rmidev_major_num);
	}
	if (retval < 0) {
		dev_err(&rmi_dev->dev,
			"Failed to get minor dev number %d, code %d.\n",
			cd->rmi_dev->number, retval);
		return retval;
	} else
		dev_info(&rmi_dev->dev, "Allocated rmidev %d %d.\n",
			 MAJOR(dev_no), MINOR(dev_no));

	data = kzalloc(sizeof(struct rmidev_data), GFP_KERNEL);
	if (!data) {
		dev_err(&rmi_dev->dev, "Failed to allocate rmidev_data.\n");
		/* unregister the char device region */
		__unregister_chrdev(rmidev_major_num, MINOR(dev_no), 1,
				CHAR_DEVICE_NAME);
		return -ENOMEM;
	}

	mutex_init(&data->file_mutex);

	data->rmi_dev = cd->rmi_dev;
	cd->data = data;

	cdev_init(&data->main_dev, &rmidev_fops);

	retval = cdev_add(&data->main_dev, dev_no, 1);
	if (retval) {
		dev_err(&cd->rmi_dev->dev, "Error %d adding rmi_char_dev.\n",
			retval);
		rmidev_device_cleanup(data);
		return retval;
	}

	dev_set_name(&cd->dev, "rmidev%d", MINOR(dev_no));
	data->device_class = rmidev_device_class;
	device_ptr = device_create(
			data->device_class,
			NULL, dev_no, NULL,
			CHAR_DEVICE_NAME"%d",
			MINOR(dev_no));

	if (IS_ERR(device_ptr)) {
		dev_err(&cd->rmi_dev->dev, "Failed to create rmi device.\n");
		rmidev_device_cleanup(data);
		return -ENODEV;
	}

	return 0;
}
Exemple #5
0
static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data)
{
	int retval;
	dev_t dev_no;
	struct device *device_ptr;
	struct rmidev_handle *rmidev = NULL;

	rmidev = kzalloc(sizeof(struct rmidev_handle), GFP_KERNEL);
	if (!rmidev) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to alloc mem for rmidev\n",
				__func__);
		retval = -ENOMEM;
		goto err_rmidev;
	}

	rmi4_data->rmidev = rmidev;
	rmidev->rmi4_data = rmi4_data;

	retval = rmidev_create_device_class(rmi4_data);
	if (retval < 0) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to create device class\n",
				__func__);
		goto err_device_class;
	}

	if (rmidev_major_num) {
		dev_no = MKDEV(rmidev_major_num, DEV_NUMBER);
		retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
	} else {
		retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
		if (retval < 0) {
			dev_err(&rmi4_data->i2c_client->dev,
					"%s: Failed to allocate char device region\n",
					__func__);
			goto err_device_region;
		}

		rmidev_major_num = MAJOR(dev_no);
		dev_dbg(&rmi4_data->i2c_client->dev,
				"%s: Major number of rmidev = %d\n",
				__func__, rmidev_major_num);
	}

	mutex_init(&rmidev->dev_data.file_mutex);
	cdev_init(&rmidev->dev_data.main_dev, &rmidev_fops);

	retval = cdev_add(&rmidev->dev_data.main_dev, dev_no, 1);
	if (retval < 0) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to add rmi char device\n",
				__func__);
		goto err_char_device;
	}

	dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no));
	rmidev->dev_data.device_class = rmidev_device_class;

	device_ptr = device_create(rmidev->dev_data.device_class, NULL, dev_no,
			NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no));
	if (IS_ERR(device_ptr)) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to create rmi char device\n",
				__func__);
		retval = -ENODEV;
		goto err_char_device;
	}

	retval = gpio_export(rmi4_data->board->gpio, false);
	if (retval < 0) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to export attention gpio\n",
				__func__);
	} else {
		retval = gpio_export_link(&(rmi4_data->input_dev->dev),
				"attn", rmi4_data->board->gpio);
		if (retval < 0) {
			dev_err(&rmi4_data->input_dev->dev,
					"%s Failed to create gpio symlink\n",
					__func__);
		} else {
			dev_dbg(&rmi4_data->input_dev->dev,
					"%s: Exported attention gpio %d\n",
					__func__, rmi4_data->board->gpio);
		}
	}

	rmidev->attr_dir = kobject_create_and_add(ATTRIBUTE_FOLDER_NAME,
			&rmi4_data->input_dev->dev.kobj);
	if (!rmidev->attr_dir) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to create sysfs directory\n",
				__func__);
		retval = -ENODEV;
		goto err_attr_dir;
	}

	retval = sysfs_create_bin_file(rmidev->attr_dir,
			&attr_data);
	if (retval < 0) {
		dev_err(&rmi4_data->i2c_client->dev,
				"%s: Failed to create sysfs bin file\n",
				__func__);
		goto err_sysfs_bin;
	}

	retval = sysfs_create_group(rmidev->attr_dir, &attr_group);
	if (retval < 0) {
		dev_err(&rmi4_data->input_dev->dev,
					"%s: Failed to create sysfs attributes\n", __func__);
			retval = -ENODEV;
			goto err_sysfs_attrs;
	}

	return 0;

err_sysfs_attrs:
	sysfs_remove_group(rmidev->attr_dir, &attr_group);
	sysfs_remove_bin_file(rmidev->attr_dir, &attr_data);

err_sysfs_bin:
	kobject_put(rmidev->attr_dir);

err_attr_dir:
err_char_device:
	rmidev_device_cleanup(&rmidev->dev_data);
	mutex_destroy(&rmidev->dev_data.file_mutex);
	unregister_chrdev_region(dev_no, 1);

err_device_region:
	class_destroy(rmidev_device_class);

err_device_class:
	kfree(rmidev);
	rmi4_data->rmidev = NULL;

err_rmidev:
	return retval;
}