35
35
#include <media/v4l2-device.h>
36
36
#include <sound/tea575x-tuner.h>
37
37
38
+ #if defined(CONFIG_LEDS_CLASS ) || \
39
+ (defined(CONFIG_LEDS_CLASS_MODULE ) && defined(CONFIG_RADIO_SHARK_MODULE ))
40
+ #define SHARK_USE_LEDS 1
41
+ #endif
42
+
38
43
/*
39
44
* Version Information
40
45
*/
@@ -56,44 +61,18 @@ MODULE_LICENSE("GPL");
56
61
57
62
enum { BLUE_LED , BLUE_PULSE_LED , RED_LED , NO_LEDS };
58
63
59
- static void shark_led_set_blue (struct led_classdev * led_cdev ,
60
- enum led_brightness value );
61
- static void shark_led_set_blue_pulse (struct led_classdev * led_cdev ,
62
- enum led_brightness value );
63
- static void shark_led_set_red (struct led_classdev * led_cdev ,
64
- enum led_brightness value );
65
-
66
- static const struct led_classdev shark_led_templates [NO_LEDS ] = {
67
- [BLUE_LED ] = {
68
- .name = "%s:blue:" ,
69
- .brightness = LED_OFF ,
70
- .max_brightness = 127 ,
71
- .brightness_set = shark_led_set_blue ,
72
- },
73
- [BLUE_PULSE_LED ] = {
74
- .name = "%s:blue-pulse:" ,
75
- .brightness = LED_OFF ,
76
- .max_brightness = 255 ,
77
- .brightness_set = shark_led_set_blue_pulse ,
78
- },
79
- [RED_LED ] = {
80
- .name = "%s:red:" ,
81
- .brightness = LED_OFF ,
82
- .max_brightness = 1 ,
83
- .brightness_set = shark_led_set_red ,
84
- },
85
- };
86
-
87
64
struct shark_device {
88
65
struct usb_device * usbdev ;
89
66
struct v4l2_device v4l2_dev ;
90
67
struct snd_tea575x tea ;
91
68
69
+ #ifdef SHARK_USE_LEDS
92
70
struct work_struct led_work ;
93
71
struct led_classdev leds [NO_LEDS ];
94
72
char led_names [NO_LEDS ][32 ];
95
73
atomic_t brightness [NO_LEDS ];
96
74
unsigned long brightness_new ;
75
+ #endif
97
76
98
77
u8 * transfer_buffer ;
99
78
u32 last_val ;
@@ -175,20 +154,13 @@ static struct snd_tea575x_ops shark_tea_ops = {
175
154
.read_val = shark_read_val ,
176
155
};
177
156
157
+ #ifdef SHARK_USE_LEDS
178
158
static void shark_led_work (struct work_struct * work )
179
159
{
180
160
struct shark_device * shark =
181
161
container_of (work , struct shark_device , led_work );
182
162
int i , res , brightness , actual_len ;
183
163
184
- /*
185
- * We use the v4l2_dev lock and registered bit to ensure the device
186
- * does not get unplugged and unreffed while we're running.
187
- */
188
- mutex_lock (& shark -> tea .mutex );
189
- if (!video_is_registered (& shark -> tea .vd ))
190
- goto leave ;
191
-
192
164
for (i = 0 ; i < 3 ; i ++ ) {
193
165
if (!test_and_clear_bit (i , & shark -> brightness_new ))
194
166
continue ;
@@ -208,8 +180,6 @@ static void shark_led_work(struct work_struct *work)
208
180
v4l2_err (& shark -> v4l2_dev , "set LED %s error: %d\n" ,
209
181
shark -> led_names [i ], res );
210
182
}
211
- leave :
212
- mutex_unlock (& shark -> tea .mutex );
213
183
}
214
184
215
185
static void shark_led_set_blue (struct led_classdev * led_cdev ,
@@ -245,19 +215,78 @@ static void shark_led_set_red(struct led_classdev *led_cdev,
245
215
schedule_work (& shark -> led_work );
246
216
}
247
217
218
+ static const struct led_classdev shark_led_templates [NO_LEDS ] = {
219
+ [BLUE_LED ] = {
220
+ .name = "%s:blue:" ,
221
+ .brightness = LED_OFF ,
222
+ .max_brightness = 127 ,
223
+ .brightness_set = shark_led_set_blue ,
224
+ },
225
+ [BLUE_PULSE_LED ] = {
226
+ .name = "%s:blue-pulse:" ,
227
+ .brightness = LED_OFF ,
228
+ .max_brightness = 255 ,
229
+ .brightness_set = shark_led_set_blue_pulse ,
230
+ },
231
+ [RED_LED ] = {
232
+ .name = "%s:red:" ,
233
+ .brightness = LED_OFF ,
234
+ .max_brightness = 1 ,
235
+ .brightness_set = shark_led_set_red ,
236
+ },
237
+ };
238
+
239
+ static int shark_register_leds (struct shark_device * shark , struct device * dev )
240
+ {
241
+ int i , retval ;
242
+
243
+ INIT_WORK (& shark -> led_work , shark_led_work );
244
+ for (i = 0 ; i < NO_LEDS ; i ++ ) {
245
+ shark -> leds [i ] = shark_led_templates [i ];
246
+ snprintf (shark -> led_names [i ], sizeof (shark -> led_names [0 ]),
247
+ shark -> leds [i ].name , shark -> v4l2_dev .name );
248
+ shark -> leds [i ].name = shark -> led_names [i ];
249
+ retval = led_classdev_register (dev , & shark -> leds [i ]);
250
+ if (retval ) {
251
+ v4l2_err (& shark -> v4l2_dev ,
252
+ "couldn't register led: %s\n" ,
253
+ shark -> led_names [i ]);
254
+ return retval ;
255
+ }
256
+ }
257
+ return 0 ;
258
+ }
259
+
260
+ static void shark_unregister_leds (struct shark_device * shark )
261
+ {
262
+ int i ;
263
+
264
+ for (i = 0 ; i < NO_LEDS ; i ++ )
265
+ led_classdev_unregister (& shark -> leds [i ]);
266
+
267
+ cancel_work_sync (& shark -> led_work );
268
+ }
269
+ #else
270
+ static int shark_register_leds (struct shark_device * shark , struct device * dev )
271
+ {
272
+ v4l2_warn (& shark -> v4l2_dev ,
273
+ "CONFIG_LED_CLASS not enabled, LED support disabled\n" );
274
+ return 0 ;
275
+ }
276
+ static inline void shark_unregister_leds (struct shark_device * shark ) { }
277
+ #endif
278
+
248
279
static void usb_shark_disconnect (struct usb_interface * intf )
249
280
{
250
281
struct v4l2_device * v4l2_dev = usb_get_intfdata (intf );
251
282
struct shark_device * shark = v4l2_dev_to_shark (v4l2_dev );
252
- int i ;
253
283
254
284
mutex_lock (& shark -> tea .mutex );
255
285
v4l2_device_disconnect (& shark -> v4l2_dev );
256
286
snd_tea575x_exit (& shark -> tea );
257
287
mutex_unlock (& shark -> tea .mutex );
258
288
259
- for (i = 0 ; i < NO_LEDS ; i ++ )
260
- led_classdev_unregister (& shark -> leds [i ]);
289
+ shark_unregister_leds (shark );
261
290
262
291
v4l2_device_put (& shark -> v4l2_dev );
263
292
}
@@ -266,7 +295,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev)
266
295
{
267
296
struct shark_device * shark = v4l2_dev_to_shark (v4l2_dev );
268
297
269
- cancel_work_sync (& shark -> led_work );
270
298
v4l2_device_unregister (& shark -> v4l2_dev );
271
299
kfree (shark -> transfer_buffer );
272
300
kfree (shark );
@@ -276,7 +304,7 @@ static int usb_shark_probe(struct usb_interface *intf,
276
304
const struct usb_device_id * id )
277
305
{
278
306
struct shark_device * shark ;
279
- int i , retval = - ENOMEM ;
307
+ int retval = - ENOMEM ;
280
308
281
309
shark = kzalloc (sizeof (struct shark_device ), GFP_KERNEL );
282
310
if (!shark )
@@ -286,17 +314,13 @@ static int usb_shark_probe(struct usb_interface *intf,
286
314
if (!shark -> transfer_buffer )
287
315
goto err_alloc_buffer ;
288
316
289
- /*
290
- * Work around a bug in usbhid/hid-core.c, where it leaves a dangling
291
- * pointer in intfdata causing v4l2-device.c to not set it. Which
292
- * results in usb_shark_disconnect() referencing the dangling pointer
293
- *
294
- * REMOVE (as soon as the above bug is fixed, patch submitted)
295
- */
296
- usb_set_intfdata (intf , NULL );
317
+ v4l2_device_set_name (& shark -> v4l2_dev , DRV_NAME , & shark_instance );
318
+
319
+ retval = shark_register_leds (shark , & intf -> dev );
320
+ if (retval )
321
+ goto err_reg_leds ;
297
322
298
323
shark -> v4l2_dev .release = usb_shark_release ;
299
- v4l2_device_set_name (& shark -> v4l2_dev , DRV_NAME , & shark_instance );
300
324
retval = v4l2_device_register (& intf -> dev , & shark -> v4l2_dev );
301
325
if (retval ) {
302
326
v4l2_err (& shark -> v4l2_dev , "couldn't register v4l2_device\n" );
@@ -320,32 +344,13 @@ static int usb_shark_probe(struct usb_interface *intf,
320
344
goto err_init_tea ;
321
345
}
322
346
323
- INIT_WORK (& shark -> led_work , shark_led_work );
324
- for (i = 0 ; i < NO_LEDS ; i ++ ) {
325
- shark -> leds [i ] = shark_led_templates [i ];
326
- snprintf (shark -> led_names [i ], sizeof (shark -> led_names [0 ]),
327
- shark -> leds [i ].name , shark -> v4l2_dev .name );
328
- shark -> leds [i ].name = shark -> led_names [i ];
329
- /*
330
- * We don't fail the probe if we fail to register the leds,
331
- * because once we've called snd_tea575x_init, the /dev/radio0
332
- * node may be opened from userspace holding a reference to us!
333
- *
334
- * Note we cannot register the leds first instead as
335
- * shark_led_work depends on the v4l2 mutex and registered bit.
336
- */
337
- retval = led_classdev_register (& intf -> dev , & shark -> leds [i ]);
338
- if (retval )
339
- v4l2_err (& shark -> v4l2_dev ,
340
- "couldn't register led: %s\n" ,
341
- shark -> led_names [i ]);
342
- }
343
-
344
347
return 0 ;
345
348
346
349
err_init_tea :
347
350
v4l2_device_unregister (& shark -> v4l2_dev );
348
351
err_reg_dev :
352
+ shark_unregister_leds (shark );
353
+ err_reg_leds :
349
354
kfree (shark -> transfer_buffer );
350
355
err_alloc_buffer :
351
356
kfree (shark );
0 commit comments