greybus: es2: fix cport-count error handling
[cascardo/linux.git] / drivers / staging / greybus / vibrator.c
1 /*
2  * Greybus Vibrator protocol driver.
3  *
4  * Copyright 2014 Google Inc.
5  * Copyright 2014 Linaro Ltd.
6  *
7  * Released under the GPLv2 only.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/device.h>
14 #include <linux/kdev_t.h>
15 #include <linux/idr.h>
16 #include "greybus.h"
17
18 struct gb_vibrator_device {
19         struct gb_connection    *connection;
20         struct device           *dev;
21         int                     minor;          /* vibrator minor number */
22 };
23
24 /* Version of the Greybus vibrator protocol we support */
25 #define GB_VIBRATOR_VERSION_MAJOR               0x00
26 #define GB_VIBRATOR_VERSION_MINOR               0x01
27
28 /* Greybus Vibrator operation types */
29 #define GB_VIBRATOR_TYPE_ON                     0x02
30 #define GB_VIBRATOR_TYPE_OFF                    0x03
31
32 struct gb_vibrator_on_request {
33         __le16  timeout_ms;
34 };
35
36 static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms)
37 {
38         struct gb_vibrator_on_request request;
39
40         request.timeout_ms = cpu_to_le16(timeout_ms);
41         return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON,
42                                  &request, sizeof(request), NULL, 0);
43 }
44
45 static int turn_off(struct gb_vibrator_device *vib)
46 {
47         return gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_OFF,
48                                  NULL, 0, NULL, 0);
49 }
50
51 static ssize_t timeout_store(struct device *dev, struct device_attribute *attr,
52                              const char *buf, size_t count)
53 {
54         struct gb_vibrator_device *vib = dev_get_drvdata(dev);
55         unsigned long val;
56         int retval;
57
58         retval = kstrtoul(buf, 10, &val);
59         if (retval < 0) {
60                 dev_err(dev, "could not parse timeout value %d\n", retval);
61                 return retval;
62         }
63
64         if (val)
65                 retval = turn_on(vib, (u16)val);
66         else
67                 retval = turn_off(vib);
68         if (retval)
69                 return retval;
70
71         return count;
72 }
73 static DEVICE_ATTR_WO(timeout);
74
75 static struct attribute *vibrator_attrs[] = {
76         &dev_attr_timeout.attr,
77         NULL,
78 };
79 ATTRIBUTE_GROUPS(vibrator);
80
81 static struct class vibrator_class = {
82         .name           = "vibrator",
83         .owner          = THIS_MODULE,
84 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
85         .dev_groups     = vibrator_groups,
86 #endif
87 };
88
89 static DEFINE_IDA(minors);
90
91 static int gb_vibrator_probe(struct gb_bundle *bundle,
92                                         const struct greybus_bundle_id *id)
93 {
94         struct greybus_descriptor_cport *cport_desc;
95         struct gb_connection *connection;
96         struct gb_vibrator_device *vib;
97         struct device *dev;
98         int retval;
99
100         if (bundle->num_cports != 1)
101                 return -ENODEV;
102
103         cport_desc = &bundle->cport_desc[0];
104         if (cport_desc->protocol_id != GREYBUS_PROTOCOL_VIBRATOR)
105                 return -ENODEV;
106
107         vib = kzalloc(sizeof(*vib), GFP_KERNEL);
108         if (!vib)
109                 return -ENOMEM;
110
111         connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
112                                                 NULL);
113         if (IS_ERR(connection)) {
114                 retval = PTR_ERR(connection);
115                 goto err_free_vib;
116         }
117         connection->private = vib;
118
119         vib->connection = connection;
120
121         greybus_set_drvdata(bundle, vib);
122
123         retval = gb_connection_enable(connection);
124         if (retval)
125                 goto err_connection_destroy;
126
127         /*
128          * For now we create a device in sysfs for the vibrator, but odds are
129          * there is a "real" device somewhere in the kernel for this, but I
130          * can't find it at the moment...
131          */
132         vib->minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
133         if (vib->minor < 0) {
134                 retval = vib->minor;
135                 goto err_connection_disable;
136         }
137         dev = device_create(&vibrator_class, &bundle->dev,
138                             MKDEV(0, 0), vib, "vibrator%d", vib->minor);
139         if (IS_ERR(dev)) {
140                 retval = -EINVAL;
141                 goto err_ida_remove;
142         }
143         vib->dev = dev;
144
145 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0)
146         /*
147          * Newer kernels handle this in a race-free manner, by the dev_groups
148          * field in the struct class up above.  But for older kernels, we need
149          * to "open code this :(
150          */
151         retval = sysfs_create_group(&dev->kobj, vibrator_groups[0]);
152         if (retval) {
153                 device_unregister(dev);
154                 goto err_ida_remove;
155         }
156 #endif
157
158         return 0;
159
160 err_ida_remove:
161         ida_simple_remove(&minors, vib->minor);
162 err_connection_disable:
163         gb_connection_disable(connection);
164 err_connection_destroy:
165         gb_connection_destroy(connection);
166 err_free_vib:
167         kfree(vib);
168
169         return retval;
170 }
171
172 static void gb_vibrator_disconnect(struct gb_bundle *bundle)
173 {
174         struct gb_vibrator_device *vib = greybus_get_drvdata(bundle);
175
176 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3,11,0)
177         sysfs_remove_group(&vib->dev->kobj, vibrator_groups[0]);
178 #endif
179         device_unregister(vib->dev);
180         ida_simple_remove(&minors, vib->minor);
181         gb_connection_disable(vib->connection);
182         gb_connection_destroy(vib->connection);
183         kfree(vib);
184 }
185
186 static const struct greybus_bundle_id gb_vibrator_id_table[] = {
187         { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
188         { }
189 };
190 MODULE_DEVICE_TABLE(greybus, gb_vibrator_id_table);
191
192 static struct greybus_driver gb_vibrator_driver = {
193         .name           = "vibrator",
194         .probe          = gb_vibrator_probe,
195         .disconnect     = gb_vibrator_disconnect,
196         .id_table       = gb_vibrator_id_table,
197 };
198
199 static __init int gb_vibrator_init(void)
200 {
201         int retval;
202
203         retval = class_register(&vibrator_class);
204         if (retval)
205                 return retval;
206
207         retval = greybus_register(&gb_vibrator_driver);
208         if (retval)
209                 goto err_class_unregister;
210
211         return 0;
212
213 err_class_unregister:
214         class_unregister(&vibrator_class);
215
216         return retval;
217 }
218 module_init(gb_vibrator_init);
219
220 static __exit void gb_vibrator_exit(void)
221 {
222         greybus_deregister(&gb_vibrator_driver);
223         class_unregister(&vibrator_class);
224         ida_destroy(&minors);
225 }
226 module_exit(gb_vibrator_exit);
227
228 MODULE_LICENSE("GPL v2");