cregit-Linux how code gets into the kernel

Release 4.11 drivers/staging/greybus/vibrator.c

/*
 * Greybus Vibrator protocol driver.
 *
 * Copyright 2014 Google Inc.
 * Copyright 2014 Linaro Ltd.
 *
 * Released under the GPLv2 only.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/idr.h>
#include <linux/pm_runtime.h>

#include "greybus.h"


struct gb_vibrator_device {
	
struct gb_connection	*connection;
	
struct device		*dev;
	
int			minor;		/* vibrator minor number */
	
struct delayed_work     delayed_work;
};

/* Greybus Vibrator operation types */

#define	GB_VIBRATOR_TYPE_ON			0x02

#define	GB_VIBRATOR_TYPE_OFF			0x03


static int turn_off(struct gb_vibrator_device *vib) { struct gb_bundle *bundle = vib->connection->bundle; int ret; ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF, NULL, 0, NULL, 0); gb_pm_runtime_put_autosuspend(bundle); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Ann Chen2751.92%250.00%
Greg Kroah-Hartman2548.08%250.00%
Total52100.00%4100.00%


static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_bundle *bundle = vib->connection->bundle; int ret; ret = gb_pm_runtime_get_sync(bundle); if (ret) return ret; /* Vibrator was switched ON earlier */ if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, NULL, 0, NULL, 0); if (ret) { gb_pm_runtime_put_autosuspend(bundle); return ret; } schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ann Chen8074.77%240.00%
Greg Kroah-Hartman2725.23%360.00%
Total107100.00%5100.00%


static void gb_vibrator_worker(struct work_struct *work) { struct delayed_work *delayed_work = to_delayed_work(work); struct gb_vibrator_device *vib = container_of(delayed_work, struct gb_vibrator_device, delayed_work); turn_off(vib); }

Contributors

PersonTokensPropCommitsCommitProp
Ann Chen41100.00%1100.00%
Total41100.00%1100.00%


static ssize_t timeout_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gb_vibrator_device *vib = dev_get_drvdata(dev); unsigned long val; int retval; retval = kstrtoul(buf, 10, &val); if (retval < 0) { dev_err(dev, "could not parse timeout value %d\n", retval); return retval; } if (val) retval = turn_on(vib, (u16)val); else retval = turn_off(vib); if (retval) return retval; return count; }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman107100.00%1100.00%
Total107100.00%1100.00%

static DEVICE_ATTR_WO(timeout); static struct attribute *vibrator_attrs[] = { &dev_attr_timeout.attr, NULL, }; ATTRIBUTE_GROUPS(vibrator); static struct class vibrator_class = { .name = "vibrator", .owner = THIS_MODULE, .dev_groups = vibrator_groups, }; static DEFINE_IDA(minors);
static int gb_vibrator_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { struct greybus_descriptor_cport *cport_desc; struct gb_connection *connection; struct gb_vibrator_device *vib; struct device *dev; int retval; if (bundle->num_cports != 1) return -ENODEV; cport_desc = &bundle->cport_desc[0]; if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR) return -ENODEV; vib = kzalloc(sizeof(*vib), GFP_KERNEL); if (!vib) return -ENOMEM; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), NULL); if (IS_ERR(connection)) { retval = PTR_ERR(connection); goto err_free_vib; } gb_connection_set_data(connection, vib); vib->connection = connection; greybus_set_drvdata(bundle, vib); retval = gb_connection_enable(connection); if (retval) goto err_connection_destroy; /* * For now we create a device in sysfs for the vibrator, but odds are * there is a "real" device somewhere in the kernel for this, but I * can't find it at the moment... */ vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); if (vib->minor < 0) { retval = vib->minor; goto err_connection_disable; } dev = device_create(&vibrator_class, &bundle->dev, MKDEV(0, 0), vib, "vibrator%d", vib->minor); if (IS_ERR(dev)) { retval = -EINVAL; goto err_ida_remove; } vib->dev = dev; INIT_DELAYED_WORK(&vib->delayed_work, gb_vibrator_worker); gb_pm_runtime_put_autosuspend(bundle); return 0; err_ida_remove: ida_simple_remove(&minors, vib->minor); err_connection_disable: gb_connection_disable(connection); err_connection_destroy: gb_connection_destroy(connection); err_free_vib: kfree(vib); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman15249.67%654.55%
Johan Hovold13644.44%218.18%
Ann Chen154.90%218.18%
Alex Elder30.98%19.09%
Total306100.00%11100.00%


static void gb_vibrator_disconnect(struct gb_bundle *bundle) { struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); int ret; ret = gb_pm_runtime_get_sync(bundle); if (ret) gb_pm_runtime_get_noresume(bundle); if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); device_unregister(vib->dev); ida_simple_remove(&minors, vib->minor); gb_connection_disable(vib->connection); gb_connection_destroy(vib->connection); kfree(vib); }

Contributors

PersonTokensPropCommitsCommitProp
Ann Chen3437.36%233.33%
Greg Kroah-Hartman2931.87%233.33%
Johan Hovold2830.77%233.33%
Total91100.00%6100.00%

static const struct greybus_bundle_id gb_vibrator_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) }, { } }; MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table); static struct greybus_driver gb_vibrator_driver = { .name = "vibrator", .probe = gb_vibrator_probe, .disconnect = gb_vibrator_disconnect, .id_table = gb_vibrator_id_table, };
static __init int gb_vibrator_init(void) { int retval; retval = class_register(&vibrator_class); if (retval) return retval; retval = greybus_register(&gb_vibrator_driver); if (retval) goto err_class_unregister; return 0; err_class_unregister: class_unregister(&vibrator_class); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman3053.57%360.00%
Johan Hovold2646.43%240.00%
Total56100.00%5100.00%

module_init(gb_vibrator_init);
static __exit void gb_vibrator_exit(void) { greybus_deregister(&gb_vibrator_driver); class_unregister(&vibrator_class); ida_destroy(&minors); }

Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman2488.89%375.00%
Johan Hovold311.11%125.00%
Total27100.00%4100.00%

module_exit(gb_vibrator_exit); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Greg Kroah-Hartman52454.24%1254.55%
Johan Hovold22923.71%418.18%
Ann Chen20421.12%29.09%
Alex Elder50.52%313.64%
Viresh Kumar40.41%14.55%
Total966100.00%22100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.