aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
blob: 522085bb2fa2e21b5b94fa4bf40e8bdd63daba9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
/*
 *  GPIO Button Hotplug driver
 *
 *  Copyright (C) 2012 Felix Fietkau <nbd@nbd.name>
 *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
 *
 *  Based on the diag.c - GPIO interface driver for Broadcom boards
 *    Copyright (C) 2006 Mike Baker <mbm@openwrt.org>,
 *    Copyright (C) 2006-2007 Felix Fietkau <nbd@nbd.name>
 *    Copyright (C) 2008 Andy Boyett <agb@openwrt.org>
 *
 *  This program is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License version 2 as published
 *  by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/version.h>
#include <linux/kmod.h>

#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/kobject.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/gpio_keys.h>
#include <linux/gpio/consumer.h>

#define BH_SKB_SIZE	2048

#define DRV_NAME	"gpio-keys"
#define PFX	DRV_NAME ": "

struct bh_event {
	const char		*name;
	unsigned int		type;
	char			*action;
	unsigned long		seen;

	struct sk_buff		*skb;
	struct work_struct	work;
};

struct bh_map {
	unsigned int	code;
	const char	*name;
};

struct gpio_keys_button_data {
	struct delayed_work work;
	unsigned long seen;
	int map_entry;
	int last_state;
	int count;
	int threshold;
	int can_sleep;
	int irq;
	unsigned int software_debounce;
	struct gpio_desc *gpiod;
	const struct gpio_keys_button *b;
};

extern u64 uevent_next_seqnum(void);

#define BH_MAP(_code, _name)		\
	{				\
		.code = (_code),	\
		.name = (_name),	\
	}

static struct bh_map button_map[] = {
	BH_MAP(BTN_0,			"BTN_0"),
	BH_MAP(BTN_1,			"BTN_1"),
	BH_MAP(BTN_2,			"BTN_2"),
	BH_MAP(BTN_3,			"BTN_3"),
	BH_MAP(BTN_4,			"BTN_4"),
	BH_MAP(BTN_5,			"BTN_5"),
	BH_MAP(BTN_6,			"BTN_6"),
	BH_MAP(BTN_7,			"BTN_7"),
	BH_MAP(BTN_8,			"BTN_8"),
	BH_MAP(BTN_9,			"BTN_9"),
	BH_MAP(KEY_BRIGHTNESS_ZERO,	"brightness_zero"),
	BH_MAP(KEY_CONFIG,		"config"),
	BH_MAP(KEY_COPY,		"copy"),
	BH_MAP(KEY_EJECTCD,		"eject"),
	BH_MAP(KEY_HELP,		"help"),
	BH_MAP(KEY_LIGHTS_TOGGLE,	"lights_toggle"),
	BH_MAP(KEY_PHONE,		"phone"),
	BH_MAP(KEY_POWER,		"power"),
	BH_MAP(KEY_POWER2,		"reboot"),
	BH_MAP(KEY_RESTART,		"reset"),
	BH_MAP(KEY_RFKILL,		"rfkill"),
	BH_MAP(KEY_VIDEO,		"video"),
	BH_MAP(KEY_VOLUMEDOWN,		"volume_down"),
	BH_MAP(KEY_VOLUMEUP,		"volume_up"),
	BH_MAP(KEY_WIMAX,		"wwan"),
	BH_MAP(KEY_WLAN,		"wlan"),
	BH_MAP(KEY_WPS_BUTTON,		"wps"),
};

/* -------------------------------------------------------------------------*/

static __printf(3, 4)
int bh_event_add_var(struct bh_event *event, int argv, const char *format, ...)
{
	char buf[128];
	char *s;
	va_list args;
	int len;

	if (argv)
		return 0;

	va_start(args, format);
	len = vsnprintf(buf, sizeof(buf), format, args);
	va_end(args);

	if (len >= sizeof(buf)) {
		WARN(1, "buffer size too small");
		return -ENOMEM;
	}

	s = skb_put(event->skb, len + 1);
	strcpy(s, buf);

	pr_debug(PFX "added variable '%s'\n", s);

	return 0;
}

static int button_hotplug_fill_event(struct bh_event *event)
{
	int ret;

	ret = bh_event_add_var(event, 0, "HOME=%s", "/");
	if (ret)
		return ret;

	ret = bh_event_add_var(event, 0, "PATH=%s",
					"/sbin:/bin:/usr/sbin:/usr/bin");
	if (ret)
		return ret;

	ret = bh_event_add_var(event, 0, "SUBSYSTEM=%s", "button");
	if (ret)
		return ret;

	ret = bh_event_add_var(event, 0, "ACTION=%s", event->action);
	if (ret)
		return ret;

	ret = bh_event_add_var(event, 0, "BUTTON=%s", event->name);
	if (ret)
		return ret;

	if (event->type == EV_SW) {
		ret = bh_event_add_var(event, 0, "TYPE=%s", "switch");
		if (ret)
			return ret;
	}

	ret = bh_event_add_var(event, 0, "SEEN=%ld", event->seen);
	if (ret)
		return ret;

	ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());

	return ret;
}

static void button_hotplug_work(struct work_struct *work)
{
	struct bh_event *event = container_of(work, struct bh_event, work);
	int ret = 0;

	event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
	if (!event->skb)
		goto out_free_event;

	ret = bh_event_add_var(event, 0, "%s@", event->action);
	if (ret)
		goto out_free_skb;

	ret = button_hotplug_fill_event(event);
	if (ret)
		goto out_free_skb;

	NETLINK_CB(event->skb).dst_group = 1;
	broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);

 out_free_skb:
	if (ret) {
		pr_err(PFX "work error %d\n", ret);
		kfree_skb(event->skb);
	}
 out_free_event:
	kfree(event);
}

static int button_hotplug_create_event(const char *name, unsigned int type,
		unsigned long seen, int pressed)
{
	struct bh_event *event;

	pr_debug(PFX "create event, name=%s, seen=%lu, pressed=%d\n",
		 name, seen, pressed);

	event = kzalloc(sizeof(*event), GFP_KERNEL);
	if (!event)
		return -ENOMEM;

	event->name = name;
	event->type = type;
	event->seen = seen;
	event->action = pressed ? "pressed" : "released";

	INIT_WORK(&event->work, (void *)(void *)button_hotplug_work);
	schedule_work(&event->work);

	return 0;
}

/* -------------------------------------------------------------------------*/

static int button_get_index(unsigned int code)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(button_map); i++)
		if (button_map[i].code == code)
			return i;

	return -1;
}

static int gpio_button_get_value(struct gpio_keys_button_data *bdata)
{
	int val;

	if (bdata->can_sleep)
		val = !!gpiod_get_value_cansleep(bdata->gpiod);
	else
		val = !!gpiod_get_value(bdata->gpiod);

	return val;
}

static void gpio_keys_handle_button(struct gpio_keys_button_data *bdata)
{
	unsigned int type = bdata->b->type ?: EV_KEY;
	int state = gpio_button_get_value(bdata);
	unsigned long seen = jiffies;

	pr_debug(PFX "event type=%u, code=%u, pressed=%d\n",
		 type, bdata->b->code, state);

	/* is this the initialization state? */
	if (bdata->last_state == -1) {
		/*
		 * Don't advertise unpressed buttons on initialization.
		 * Just save their state and continue otherwise this
		 * can cause OpenWrt to enter failsafe.
		 */
		if (type == EV_KEY && state == 0)
			goto set_state;
		/*
		 * But we are very interested in pressed buttons and
		 * initial switch state. These will be reported to
		 * userland.
		 */
	} else if (bdata->last_state == state) {
		/* reset asserted counter (only relevant for polled keys) */
		bdata->count = 0;
		return;
	}

	if (bdata->count < bdata->threshold) {
		bdata->count++;
		return;
	}

	if (bdata->seen == 0)
		bdata->seen = seen;

	button_hotplug_create_event(button_map[bdata->map_entry].name, type,
				    (seen - bdata->seen) / HZ, state);
	bdata->seen = seen;

set_state:
	bdata->last_state = state;
	bdata->count = 0;
}

struct gpio_keys_button_dev {
	int polled;
	struct delayed_work work;

	struct device *dev;
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button_data data[0];
};

static void gpio_keys_polled_queue_work(struct gpio_keys_button_dev *bdev)
{
	struct gpio_keys_platform_data *pdata = bdev->pdata;
	unsigned long delay = msecs_to_jiffies(pdata->poll_interval);

	if (delay >= HZ)
		delay = round_jiffies_relative(delay);
	schedule_delayed_work(&bdev->work, delay);
}

static void gpio_keys_polled_poll(struct work_struct *work)
{
	struct gpio_keys_button_dev *bdev =
		container_of(work, struct gpio_keys_button_dev, work.work);
	int i;

	for (i = 0; i < bdev->pdata->nbuttons; i++) {
		struct gpio_keys_button_data *bdata = &bdev->data[i];

		if (bdata->gpiod)
			gpio_keys_handle_button(bdata);
	}
	gpio_keys_polled_queue_work(bdev);
}

static void gpio_keys_polled_close(struct gpio_keys_button_dev *bdev)
{
	struct gpio_keys_platform_data *pdata = bdev->pdata;

	cancel_delayed_work_sync(&bdev->work);

	if (pdata->disable)
		pdata->disable(bdev->dev);
}

static void gpio_keys_irq_work_func(struct work_struct *work)
{
	struct gpio_keys_button_data *bdata = container_of(work,
		struct gpio_keys_button_data, work.work);

	gpio_keys_handle_button(bdata);
}

static irqreturn_t button_handle_irq(int irq, void *_bdata)
{
	struct gpio_keys_button_data *bdata =
		(struct gpio_keys_button_data *) _bdata;

	mod_delayed_work(system_wq, &bdata->work,
			 msecs_to_jiffies(bdata->software_debounce));

	return IRQ_HANDLED;
}

#ifdef CONFIG_OF
static struct gpio_keys_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{
	struct device_node *node, *pp;
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button *button;
	int nbuttons;
	int i = 0;

	node = dev->of_node;
	if (!node)
		return NULL;

	nbuttons = of_get_child_count(node);
	if (nbuttons == 0)
		return ERR_PTR(-EINVAL);

	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * (sizeof *button),
		GFP_KERNEL);
	if (!pdata)
		return ERR_PTR(-ENOMEM);

	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
	pdata->nbuttons = nbuttons;

	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);

	for_each_child_of_node(node, pp) {
		button = (struct gpio_keys_button *)(&pdata->buttons[i++]);

		if (of_property_read_u32(pp, "linux,code", &button->code)) {
			dev_err(dev, "Button node '%s' without keycode\n",
				pp->full_name);
			of_node_put(pp);
			return ERR_PTR(-EINVAL);
		}

		button->desc = of_get_property(pp, "label", NULL);

		if (of_property_read_u32(pp, "linux,input-type", &button->type))
			button->type = EV_KEY;

		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);

		if (of_property_read_u32(pp, "debounce-interval",
					&button->debounce_interval))
			button->debounce_interval = 5;

		button->irq = irq_of_parse_and_map(pp, 0);
		button->gpio = -ENOENT; /* mark this as device-tree */
	}

	return pdata;
}

static struct of_device_id gpio_keys_of_match[] = {
	{ .compatible = "gpio-keys", },
	{ },
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);

static struct of_device_id gpio_keys_polled_of_match[] = {
	{ .compatible = "gpio-keys-polled", },
	{ },
};
MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);

#else

static inline struct gpio_keys_platform_data *
gpio_keys_get_devtree_pdata(struct device *dev)
{
	return NULL;
}
#endif

static int gpio_keys_button_probe(struct platform_device *pdev,
		struct gpio_keys_button_dev **_bdev, int polled)
{
	struct device *dev = &pdev->dev;
	struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
	struct gpio_keys_button_dev *bdev;
	struct gpio_keys_button *buttons;
	struct device_node *prev = NULL;
	int error = 0;
	int i;

	if (!pdata) {
		pdata = gpio_keys_get_devtree_pdata(dev);
		if (IS_ERR(pdata))
			return PTR_ERR(pdata);
		if (!pdata) {
			dev_err(dev, "missing platform data\n");
			return -EINVAL;
		}
	}

	if (polled && !pdata->poll_interval) {
		dev_err(dev, "missing poll_interval value\n");
		return -EINVAL;
	}

	buttons = devm_kzalloc(dev, pdata->nbuttons * sizeof(struct gpio_keys_button),
		       GFP_KERNEL);
	if (!buttons) {
		dev_err(dev, "no memory for button data\n");
		return -ENOMEM;
	}
	memcpy(buttons, pdata->buttons, pdata->nbuttons * sizeof(struct gpio_keys_button));

	bdev = devm_kzalloc(dev, sizeof(struct gpio_keys_button_dev) +
		       pdata->nbuttons * sizeof(struct gpio_keys_button_data),
		       GFP_KERNEL);
	if (!bdev) {
		dev_err(dev, "no memory for private data\n");
		return -ENOMEM;
	}

	bdev->polled = polled;

	for (i = 0; i < pdata->nbuttons; i++) {
		struct gpio_keys_button *button = &buttons[i];
		struct gpio_keys_button_data *bdata = &bdev->data[i];
		const char *desc = button->desc ? button->desc : DRV_NAME;

		if (button->wakeup) {
			dev_err(dev, "does not support wakeup\n");
			error = -EINVAL;
			goto out;
		}

		bdata->map_entry = button_get_index(button->code);
		if (bdata->map_entry < 0) {
			dev_err(dev, "does not support key code:%u\n",
				button->code);
			error = -EINVAL;
			goto out;
		}

		if (!(button->type == 0 || button->type == EV_KEY ||
		      button->type == EV_SW)) {
			dev_err(dev, "only supports buttons or switches\n");
			error = -EINVAL;
			goto out;
		}

		if (button->irq) {
			dev_err(dev, "skipping button %s (only gpio buttons supported)\n",
				button->desc);
			bdata->b = &pdata->buttons[i];
			continue;
		}

		if (gpio_is_valid(button->gpio)) {
			/* legacy platform data... but is it the lookup table? */
			bdata->gpiod = devm_gpiod_get_index(dev, desc, i,
							    GPIOD_IN);
			if (IS_ERR(bdata->gpiod)) {
				/* or the legacy (button->gpio is good) way? */
				error = devm_gpio_request_one(dev,
					button->gpio, GPIOF_IN | (
					button->active_low ? GPIOF_ACTIVE_LOW :
					0), desc);
				if (error) {
					if (error != -EPROBE_DEFER) {
						dev_err(dev, "unable to claim gpio %d, err=%d\n",
							button->gpio, error);
					}
					goto out;
				}

				bdata->gpiod = gpio_to_desc(button->gpio);
			}
		} else {
			/* Device-tree */
			struct device_node *child =
				of_get_next_child(dev->of_node, prev);

			bdata->gpiod = devm_gpiod_get_from_of_node(dev,
				child, "gpios", 0, GPIOD_IN, desc);

			prev = child;
		}

		if (IS_ERR_OR_NULL(bdata->gpiod)) {
			error = IS_ERR(bdata->gpiod) ? PTR_ERR(bdata->gpiod) :
				-EINVAL;
			goto out;
		}

		bdata->can_sleep = gpiod_cansleep(bdata->gpiod);
		bdata->last_state = -1; /* Unknown state on boot */

		if (bdev->polled) {
			bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
							pdata->poll_interval);
		} else {
			/* bdata->threshold = 0; already initialized */

			if (button->debounce_interval) {
				error = gpiod_set_debounce(bdata->gpiod,
					button->debounce_interval * 1000);
				/*
				 * use timer if gpiolib doesn't provide
				 * debounce.
				 */
				if (error < 0) {
					bdata->software_debounce =
						button->debounce_interval;
				}
			}
		}

		bdata->b = &pdata->buttons[i];
	}

	bdev->dev = &pdev->dev;
	bdev->pdata = pdata;
	platform_set_drvdata(pdev, bdev);

	*_bdev = bdev;
	error = 0;

out:
	of_node_put(prev);
	return error;
}

static int gpio_keys_probe(struct platform_device *pdev)
{
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button_dev *bdev;
	int ret, i;

	ret = gpio_keys_button_probe(pdev, &bdev, 0);
	if (ret)
		return ret;

	pdata = bdev->pdata;
	for (i = 0; i < pdata->nbuttons; i++) {
		const struct gpio_keys_button *button = &pdata->buttons[i];
		struct gpio_keys_button_data *bdata = &bdev->data[i];
		unsigned long irqflags = IRQF_ONESHOT;

		INIT_DELAYED_WORK(&bdata->work, gpio_keys_irq_work_func);

		if (!button->irq) {
			bdata->irq = gpiod_to_irq(bdata->gpiod);
			if (bdata->irq < 0) {
				dev_err(&pdev->dev, "failed to get irq for gpio:%d\n",
					button->gpio);
				continue;
			}

			irqflags |= IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
		} else {
			bdata->irq = button->irq;
		}

		schedule_delayed_work(&bdata->work,
				      msecs_to_jiffies(bdata->software_debounce));

		ret = devm_request_threaded_irq(&pdev->dev,
			bdata->irq, NULL, button_handle_irq,
			irqflags, dev_name(&pdev->dev), bdata);
		if (ret < 0) {
			bdata->irq = 0;
			dev_err(&pdev->dev, "failed to request irq:%d for gpio:%d\n",
				bdata->irq, button->gpio);
			continue;
		} else {
			dev_dbg(&pdev->dev, "gpio:%d has irq:%d\n",
				button->gpio, bdata->irq);
		}
	}

	return 0;
}

static int gpio_keys_polled_probe(struct platform_device *pdev)
{
	struct gpio_keys_platform_data *pdata;
	struct gpio_keys_button_dev *bdev;
	int ret;

	ret = gpio_keys_button_probe(pdev, &bdev, 1);
	if (ret)
		return ret;

	INIT_DELAYED_WORK(&bdev->work, gpio_keys_polled_poll);

	pdata = bdev->pdata;
	if (pdata->enable)
		pdata->enable(bdev->dev);

	gpio_keys_polled_queue_work(bdev);

	return ret;
}

static void gpio_keys_irq_close(struct gpio_keys_button_dev *bdev)
{
	struct gpio_keys_platform_data *pdata = bdev->pdata;
	size_t i;

	for (i = 0; i < pdata->nbuttons; i++) {
		struct gpio_keys_button_data *bdata = &bdev->data[i];

		disable_irq(bdata->irq);
		cancel_delayed_work_sync(&bdata->work);
	}
}

static int gpio_keys_remove(struct platform_device *pdev)
{
	struct gpio_keys_button_dev *bdev = platform_get_drvdata(pdev);

	platform_set_drvdata(pdev, NULL);

	if (bdev->polled)
		gpio_keys_polled_close(bdev);
	else
		gpio_keys_irq_close(bdev);

	return 0;
}

static struct platform_driver gpio_keys_driver = {
	.probe	= gpio_keys_probe,
	.remove	= gpio_keys_remove,
	.driver	= {
		.name	= "gpio-keys",
		.owner	= THIS_MODULE,
		.of_match_table = of_match_ptr(gpio_keys_of_match),
	},
};

static struct platform_driver gpio_keys_polled_driver = {
	.probe	= gpio_keys_polled_probe,
	.remove	= gpio_keys_remove,
	.driver	= {
		.name	= "gpio-keys-polled",
		.owner	= THIS_MODULE,
		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
	},
};

static int __init gpio_button_init(void)
{
	int ret;

	ret = platform_driver_register(&gpio_keys_driver);
	if (ret)
		return ret;

	ret = platform_driver_register(&gpio_keys_polled_driver);
	if (ret)
		platform_driver_unregister(&gpio_keys_driver);

	return ret;
}

static void __exit gpio_button_exit(void)
{
	platform_driver_unregister(&gpio_keys_driver);
	platform_driver_unregister(&gpio_keys_polled_driver);
}

module_init(gpio_button_init);
module_exit(gpio_button_exit);

MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>");
MODULE_DESCRIPTION("Polled GPIO Buttons hotplug driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
n> $(eval $(call KernelPackage,usb-serial-oti6858)) define KernelPackage/usb-serial-sierrawireless TITLE:=Support for Sierra Wireless devices KCONFIG:=CONFIG_USB_SERIAL_SIERRAWIRELESS FILES:=$(LINUX_DIR)/drivers/usb/serial/sierra.ko AUTOLOAD:=$(call AutoProbe,sierra) $(call AddDepends/usb-serial) endef define KernelPackage/usb-serial-sierrawireless/description Kernel support for Sierra Wireless devices endef $(eval $(call KernelPackage,usb-serial-sierrawireless)) define KernelPackage/usb-serial-visor TITLE:=Support for Handspring Visor devices KCONFIG:=CONFIG_USB_SERIAL_VISOR FILES:=$(LINUX_DIR)/drivers/usb/serial/visor.ko AUTOLOAD:=$(call AutoProbe,visor) $(call AddDepends/usb-serial) endef define KernelPackage/usb-serial-visor/description Kernel support for Handspring Visor PDAs endef $(eval $(call KernelPackage,usb-serial-visor)) define KernelPackage/usb-serial-cypress-m8 TITLE:=Support for CypressM8 USB-Serial KCONFIG:=CONFIG_USB_SERIAL_CYPRESS_M8 FILES:=$(LINUX_DIR)/drivers/usb/serial/cypress_m8.ko AUTOLOAD:=$(call AutoProbe,cypress_m8) $(call AddDepends/usb-serial) endef define KernelPackage/usb-serial-cypress-m8/description Kernel support for devices with Cypress M8 USB to Serial chip (for example, the Delorme Earthmate LT-20 GPS) Supported microcontrollers in the CY4601 family are: CY7C63741 CY7C63742 CY7C63743 CY7C64013 endef $(eval $(call KernelPackage,usb-serial-cypress-m8)) define KernelPackage/usb-serial-keyspan TITLE:=Support for Keyspan USB-to-Serial devices KCONFIG:= \ CONFIG_USB_SERIAL_KEYSPAN \ CONFIG_USB_SERIAL_KEYSPAN_USA28 \ CONFIG_USB_SERIAL_KEYSPAN_USA28X \ CONFIG_USB_SERIAL_KEYSPAN_USA28XA \ CONFIG_USB_SERIAL_KEYSPAN_USA28XB \ CONFIG_USB_SERIAL_KEYSPAN_USA19 \ CONFIG_USB_SERIAL_KEYSPAN_USA18X \ CONFIG_USB_SERIAL_KEYSPAN_USA19W \ CONFIG_USB_SERIAL_KEYSPAN_USA19QW \ CONFIG_USB_SERIAL_KEYSPAN_USA19QI \ CONFIG_USB_SERIAL_KEYSPAN_MPR \ CONFIG_USB_SERIAL_KEYSPAN_USA49W \ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC FILES:= \ $(LINUX_DIR)/drivers/usb/serial/keyspan.ko \ $(wildcard $(LINUX_DIR)/drivers/usb/misc/ezusb.ko) AUTOLOAD:=$(call AutoProbe,ezusb keyspan) $(call AddDepends/usb-serial) endef define KernelPackage/usb-serial-keyspan/description Kernel support for Keyspan USB-to-Serial devices endef $(eval $(call KernelPackage,usb-serial-keyspan)) define KernelPackage/usb-serial-wwan TITLE:=Support for GSM and CDMA modems KCONFIG:=CONFIG_USB_SERIAL_WWAN FILES:=$(LINUX_DIR)/drivers/usb/serial/usb_wwan.ko HIDDEN:=1 AUTOLOAD:=$(call AutoProbe,usb_wwan) $(call AddDepends/usb-serial) endef define KernelPackage/usb-serial-wwan/description Kernel support for USB GSM and CDMA modems endef $(eval $(call KernelPackage,usb-serial-wwan)) define KernelPackage/usb-serial-option TITLE:=Support for Option HSDPA modems KCONFIG:=CONFIG_USB_SERIAL_OPTION FILES:=$(LINUX_DIR)/drivers/usb/serial/option.ko AUTOLOAD:=$(call AutoProbe,option) $(call AddDepends/usb-serial,+kmod-usb-serial-wwan) endef define KernelPackage/usb-serial-option/description Kernel support for Option HSDPA modems endef $(eval $(call KernelPackage,usb-serial-option)) define KernelPackage/usb-serial-qualcomm TITLE:=Support for Qualcomm USB serial KCONFIG:=CONFIG_USB_SERIAL_QUALCOMM FILES:=$(LINUX_DIR)/drivers/usb/serial/qcserial.ko AUTOLOAD:=$(call AutoProbe,qcserial) $(call AddDepends/usb-serial,+kmod-usb-serial-wwan) endef define KernelPackage/usb-serial-qualcomm/description Kernel support for Qualcomm USB Serial devices (Gobi) endef $(eval $(call KernelPackage,usb-serial-qualcomm)) define KernelPackage/usb-storage TITLE:=USB Storage support DEPENDS:= +kmod-scsi-core KCONFIG:=CONFIG_USB_STORAGE FILES:=$(LINUX_DIR)/drivers/usb/storage/usb-storage.ko AUTOLOAD:=$(call AutoProbe,usb-storage,1) $(call AddDepends/usb) endef define KernelPackage/usb-storage/description Kernel support for USB Mass Storage devices endef $(eval $(call KernelPackage,usb-storage)) define KernelPackage/usb-storage-extras SUBMENU:=$(USB_MENU) TITLE:=Extra drivers for usb-storage DEPENDS:=+kmod-usb-storage KCONFIG:= \ CONFIG_USB_STORAGE_ALAUDA \ CONFIG_USB_STORAGE_CYPRESS_ATACB \ CONFIG_USB_STORAGE_DATAFAB \ CONFIG_USB_STORAGE_FREECOM \ CONFIG_USB_STORAGE_ISD200 \ CONFIG_USB_STORAGE_JUMPSHOT \ CONFIG_USB_STORAGE_KARMA \ CONFIG_USB_STORAGE_SDDR09 \ CONFIG_USB_STORAGE_SDDR55 \ CONFIG_USB_STORAGE_USBAT FILES:= \ $(LINUX_DIR)/drivers/usb/storage/ums-alauda.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-cypress.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-datafab.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-freecom.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-isd200.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-jumpshot.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-karma.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-sddr09.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-sddr55.ko \ $(LINUX_DIR)/drivers/usb/storage/ums-usbat.ko AUTOLOAD:=$(call AutoProbe,ums-alauda ums-cypress ums-datafab \ ums-freecom ums-isd200 ums-jumpshot \ ums-karma ums-sddr09 ums-sddr55 ums-usbat) endef define KernelPackage/usb-storage-extras/description Say Y here if you want to have some more drivers, such as for SmartMedia card readers endef $(eval $(call KernelPackage,usb-storage-extras)) define KernelPackage/usb-storage-uas SUBMENU:=$(USB_MENU) TITLE:=USB Attached SCSI (UASP) support DEPENDS:=+kmod-usb-storage KCONFIG:=CONFIG_USB_UAS FILES:=$(LINUX_DIR)/drivers/usb/storage/uas.ko AUTOLOAD:=$(call AutoProbe,uas,1) endef define KernelPackage/usb-storage-uas/description Say Y here if you want to include support for USB Attached SCSI (UAS/UASP), a higher performance protocol available on many newer USB 3.0 storage devices endef $(eval $(call KernelPackage,usb-storage-uas)) define KernelPackage/usb-atm TITLE:=Support for ATM on USB bus DEPENDS:=+kmod-atm KCONFIG:=CONFIG_USB_ATM FILES:=$(LINUX_DIR)/drivers/usb/atm/usbatm.ko AUTOLOAD:=$(call AutoProbe,usbatm) $(call AddDepends/usb) endef define KernelPackage/usb-atm/description Kernel support for USB DSL modems endef $(eval $(call KernelPackage,usb-atm)) define AddDepends/usb-atm SUBMENU:=$(USB_MENU) DEPENDS+=kmod-usb-atm $(1) endef define KernelPackage/usb-atm-speedtouch TITLE:=SpeedTouch USB ADSL modems support KCONFIG:=CONFIG_USB_SPEEDTOUCH FILES:=$(LINUX_DIR)/drivers/usb/atm/speedtch.ko AUTOLOAD:=$(call AutoProbe,speedtch) $(call AddDepends/usb-atm) endef define KernelPackage/usb-atm-speedtouch/description Kernel support for SpeedTouch USB ADSL modems endef $(eval $(call KernelPackage,usb-atm-speedtouch)) define KernelPackage/usb-atm-ueagle TITLE:=Eagle 8051 based USB ADSL modems support FILES:=$(LINUX_DIR)/drivers/usb/atm/ueagle-atm.ko KCONFIG:=CONFIG_USB_UEAGLEATM AUTOLOAD:=$(call AutoProbe,ueagle-atm) $(call AddDepends/usb-atm) endef define KernelPackage/usb-atm-ueagle/description Kernel support for Eagle 8051 based USB ADSL modems endef $(eval $(call KernelPackage,usb-atm-ueagle)) define KernelPackage/usb-atm-cxacru TITLE:=cxacru FILES:=$(LINUX_DIR)/drivers/usb/atm/cxacru.ko KCONFIG:=CONFIG_USB_CXACRU AUTOLOAD:=$(call AutoProbe,cxacru) $(call AddDepends/usb-atm) endef define KernelPackage/usb-atm-cxacru/description Kernel support for cxacru based USB ADSL modems endef $(eval $(call KernelPackage,usb-atm-cxacru)) define KernelPackage/usb-net TITLE:=Kernel modules for USB-to-Ethernet convertors DEPENDS:=+kmod-mii KCONFIG:=CONFIG_USB_USBNET \ CONFIG_USB_NET_DRIVERS AUTOLOAD:=$(call AutoProbe,usbnet) FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/usbnet.ko $(call AddDepends/usb) endef define KernelPackage/usb-net/description Kernel modules for USB-to-Ethernet convertors endef $(eval $(call KernelPackage,usb-net)) define AddDepends/usb-net SUBMENU:=$(USB_MENU) DEPENDS+=kmod-usb-net $(1) endef define KernelPackage/usb-net-asix TITLE:=Kernel module for USB-to-Ethernet Asix convertors DEPENDS:=+kmod-libphy KCONFIG:=CONFIG_USB_NET_AX8817X FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/asix.ko AUTOLOAD:=$(call AutoProbe,asix) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-asix/description Kernel module for USB-to-Ethernet Asix convertors endef $(eval $(call KernelPackage,usb-net-asix)) define KernelPackage/usb-net-asix-ax88179 TITLE:=Kernel module for USB-to-Gigabit-Ethernet Asix convertors DEPENDS:=+kmod-libphy KCONFIG:=CONFIG_USB_NET_AX88179_178A FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/ax88179_178a.ko AUTOLOAD:=$(call AutoProbe,ax88179_178a) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-asix-ax88179/description Kernel module for USB-to-Ethernet ASIX AX88179 based USB 3.0/2.0 to Gigabit Ethernet adapters. endef $(eval $(call KernelPackage,usb-net-asix-ax88179)) define KernelPackage/usb-net-hso TITLE:=Kernel module for Option USB High Speed Mobile Devices KCONFIG:=CONFIG_USB_HSO FILES:= \ $(LINUX_DIR)/drivers/$(USBNET_DIR)/hso.ko AUTOLOAD:=$(call AutoProbe,hso) $(call AddDepends/usb-net) $(call AddDepends/rfkill) endef define KernelPackage/usb-net-hso/description Kernel module for Option USB High Speed Mobile Devices endef $(eval $(call KernelPackage,usb-net-hso)) define KernelPackage/usb-net-kaweth TITLE:=Kernel module for USB-to-Ethernet Kaweth convertors KCONFIG:=CONFIG_USB_KAWETH FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/kaweth.ko AUTOLOAD:=$(call AutoProbe,kaweth) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-kaweth/description Kernel module for USB-to-Ethernet Kaweth convertors endef $(eval $(call KernelPackage,usb-net-kaweth)) define KernelPackage/usb-net-pegasus TITLE:=Kernel module for USB-to-Ethernet Pegasus convertors KCONFIG:=CONFIG_USB_PEGASUS FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/pegasus.ko AUTOLOAD:=$(call AutoProbe,pegasus) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-pegasus/description Kernel module for USB-to-Ethernet Pegasus convertors endef $(eval $(call KernelPackage,usb-net-pegasus)) define KernelPackage/usb-net-mcs7830 TITLE:=Kernel module for USB-to-Ethernet MCS7830 convertors KCONFIG:=CONFIG_USB_NET_MCS7830 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/mcs7830.ko AUTOLOAD:=$(call AutoProbe,mcs7830) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-mcs7830/description Kernel module for USB-to-Ethernet MCS7830 convertors endef $(eval $(call KernelPackage,usb-net-mcs7830)) define KernelPackage/usb-net-smsc95xx TITLE:=SMSC LAN95XX based USB 2.0 10/100 ethernet devices KCONFIG:=CONFIG_USB_NET_SMSC95XX FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/smsc95xx.ko AUTOLOAD:=$(call AutoProbe,smsc95xx) $(call AddDepends/usb-net, +kmod-lib-crc16) endef define KernelPackage/usb-net-smsc95xx/description Kernel module for SMSC LAN95XX based devices endef $(eval $(call KernelPackage,usb-net-smsc95xx)) define KernelPackage/usb-net-dm9601-ether TITLE:=Support for DM9601 ethernet connections KCONFIG:=CONFIG_USB_NET_DM9601 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/dm9601.ko AUTOLOAD:=$(call AutoProbe,dm9601) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-dm9601-ether/description Kernel support for USB DM9601 devices endef $(eval $(call KernelPackage,usb-net-dm9601-ether)) define KernelPackage/usb-net-cdc-ether TITLE:=Support for cdc ethernet connections KCONFIG:=CONFIG_USB_NET_CDCETHER FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_ether.ko AUTOLOAD:=$(call AutoProbe,cdc_ether) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-cdc-ether/description Kernel support for USB CDC Ethernet devices endef $(eval $(call KernelPackage,usb-net-cdc-ether)) define KernelPackage/usb-net-cdc-eem TITLE:=Support for CDC EEM connections KCONFIG:=CONFIG_USB_NET_CDC_EEM FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_eem.ko AUTOLOAD:=$(call AutoProbe,cdc_eem) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-cdc-eem/description Kernel support for USB CDC EEM endef $(eval $(call KernelPackage,usb-net-cdc-eem)) define KernelPackage/usb-net-cdc-subset TITLE:=Support for CDC Ethernet subset connections KCONFIG:= \ CONFIG_USB_NET_CDC_SUBSET \ CONFIG_USB_ARMLINUX FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_subset.ko AUTOLOAD:=$(call AutoProbe,cdc_subset) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-cdc-subset/description Kernel support for Simple USB Network Links (CDC Ethernet subset) endef $(eval $(call KernelPackage,usb-net-cdc-subset)) define KernelPackage/usb-net-qmi-wwan TITLE:=QMI WWAN driver KCONFIG:=CONFIG_USB_NET_QMI_WWAN FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/qmi_wwan.ko AUTOLOAD:=$(call AutoProbe,qmi_wwan) $(call AddDepends/usb-net,+kmod-usb-wdm) endef define KernelPackage/usb-net-qmi-wwan/description QMI WWAN driver for Qualcomm MSM based 3G and LTE modems endef $(eval $(call KernelPackage,usb-net-qmi-wwan)) define KernelPackage/usb-net-rtl8150 TITLE:=Kernel module for USB-to-Ethernet Realtek convertors KCONFIG:=CONFIG_USB_RTL8150 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/rtl8150.ko AUTOLOAD:=$(call AutoProbe,rtl8150) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-rtl8150/description Kernel module for USB-to-Ethernet Realtek 8150 convertors endef $(eval $(call KernelPackage,usb-net-rtl8150)) define KernelPackage/usb-net-rtl8152 TITLE:=Kernel module for USB-to-Ethernet Realtek convertors KCONFIG:=CONFIG_USB_RTL8152 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/r8152.ko AUTOLOAD:=$(call AutoProbe,r8152) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-rtl8152/description Kernel module for USB-to-Ethernet Realtek 8152 USB2.0/3.0 convertors endef $(eval $(call KernelPackage,usb-net-rtl8152)) define KernelPackage/usb-net-sr9700 TITLE:=Support for CoreChip SR9700 ethernet devices KCONFIG:=CONFIG_USB_NET_SR9700 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/sr9700.ko AUTOLOAD:=$(call AutoProbe,sr9700) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-sr9700/description Kernel module for CoreChip-sz SR9700 based USB 1.1 10/100 ethernet devices endef $(eval $(call KernelPackage,usb-net-sr9700)) define KernelPackage/usb-net-rndis TITLE:=Support for RNDIS connections KCONFIG:=CONFIG_USB_NET_RNDIS_HOST FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/rndis_host.ko AUTOLOAD:=$(call AutoProbe,rndis_host) $(call AddDepends/usb-net,+kmod-usb-net-cdc-ether) endef define KernelPackage/usb-net-rndis/description Kernel support for RNDIS connections endef $(eval $(call KernelPackage,usb-net-rndis)) define KernelPackage/usb-net-cdc-mbim SUBMENU:=$(USB_MENU) TITLE:=Kernel module for MBIM Devices KCONFIG:=CONFIG_USB_NET_CDC_MBIM FILES:= \ $(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_mbim.ko AUTOLOAD:=$(call AutoProbe,cdc_mbim) $(call AddDepends/usb-net,+kmod-usb-wdm +kmod-usb-net-cdc-ncm) endef define KernelPackage/usb-net-cdc-mbim/description Kernel module for CDC MBIM (Mobile Broadband Interface Model) devices endef $(eval $(call KernelPackage,usb-net-cdc-mbim)) define KernelPackage/usb-net-cdc-ncm TITLE:=Support for CDC NCM connections KCONFIG:=CONFIG_USB_NET_CDC_NCM FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/cdc_ncm.ko AUTOLOAD:=$(call AutoProbe,cdc_ncm) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-cdc-ncm/description Kernel support for CDC NCM connections endef $(eval $(call KernelPackage,usb-net-cdc-ncm)) define KernelPackage/usb-net-huawei-cdc-ncm TITLE:=Support for Huawei CDC NCM connections KCONFIG:=CONFIG_USB_NET_HUAWEI_CDC_NCM FILES:= $(LINUX_DIR)/drivers/$(USBNET_DIR)/huawei_cdc_ncm.ko AUTOLOAD:=$(call AutoProbe,huawei_cdc_ncm) $(call AddDepends/usb-net,+kmod-usb-net-cdc-ncm +kmod-usb-wdm) endef define KernelPackage/usb-net-huawei-cdc-ncm/description Kernel support for Huawei CDC NCM connections endef $(eval $(call KernelPackage,usb-net-huawei-cdc-ncm)) define KernelPackage/usb-net-sierrawireless TITLE:=Support for Sierra Wireless devices KCONFIG:=CONFIG_USB_SIERRA_NET FILES:=$(LINUX_DIR)/drivers/net/usb/sierra_net.ko AUTOLOAD:=$(call AutoProbe,sierra_net) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-sierrawireless/description Kernel support for Sierra Wireless devices endef $(eval $(call KernelPackage,usb-net-sierrawireless)) define KernelPackage/usb-net-ipheth TITLE:=Apple iPhone USB Ethernet driver KCONFIG:=CONFIG_USB_IPHETH FILES:=$(LINUX_DIR)/drivers/net/usb/ipheth.ko AUTOLOAD:=$(call AutoProbe,ipheth) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-ipheth/description Kernel support for Apple iPhone USB Ethernet driver endef $(eval $(call KernelPackage,usb-net-ipheth)) define KernelPackage/usb-net-kalmia TITLE:=Samsung Kalmia based LTE USB modem KCONFIG:=CONFIG_USB_NET_KALMIA FILES:=$(LINUX_DIR)/drivers/net/usb/kalmia.ko AUTOLOAD:=$(call AutoProbe,kalmia) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-kalmia/description Kernel support for Samsung Kalmia based LTE USB modem endef $(eval $(call KernelPackage,usb-net-kalmia)) define KernelPackage/usb-net-pl TITLE:=Prolific PL-2301/2302/25A1 based cables KCONFIG:=CONFIG_USB_NET_PLUSB FILES:=$(LINUX_DIR)/drivers/net/usb/plusb.ko AUTOLOAD:=$(call AutoProbe,plusb) $(call AddDepends/usb-net) endef define KernelPackage/usb-net-pl/description Kernel support for Prolific PL-2301/2302/25A1 based cables endef $(eval $(call KernelPackage,usb-net-pl)) define KernelPackage/usb-hid TITLE:=Support for USB Human Input Devices KCONFIG:=CONFIG_HID_SUPPORT=y CONFIG_USB_HID CONFIG_USB_HIDDEV=y DEPENDS:=+kmod-hid +kmod-hid-generic +kmod-input-evdev FILES:=$(LINUX_DIR)/drivers/$(USBHID_DIR)/usbhid.ko AUTOLOAD:=$(call AutoProbe,usbhid) $(call AddDepends/usb) endef define KernelPackage/usb-hid/description Kernel support for USB HID devices such as keyboards and mice endef $(eval $(call KernelPackage,usb-hid)) define KernelPackage/usb-yealink TITLE:=USB Yealink VOIP phone DEPENDS:=+kmod-input-evdev KCONFIG:=CONFIG_USB_YEALINK CONFIG_INPUT_YEALINK CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/yealink.ko AUTOLOAD:=$(call AutoProbe,yealink) $(call AddDepends/usb) endef define KernelPackage/usb-yealink/description Kernel support for Yealink VOIP phone endef $(eval $(call KernelPackage,usb-yealink)) define KernelPackage/usb-cm109 TITLE:=Support for CM109 device DEPENDS:=+kmod-input-evdev KCONFIG:=CONFIG_USB_CM109 CONFIG_INPUT_CM109 CONFIG_INPUT=m CONFIG_INPUT_MISC=y FILES:=$(LINUX_DIR)/drivers/$(USBINPUT_DIR)/cm109.ko AUTOLOAD:=$(call AutoProbe,cm109) $(call AddDepends/usb) endef define KernelPackage/usb-cm109/description Kernel support for CM109 VOIP phone endef $(eval $(call KernelPackage,usb-cm109)) define KernelPackage/usb-test TITLE:=USB Testing Driver DEPENDS:=@DEVEL KCONFIG:=CONFIG_USB_TEST FILES:=$(LINUX_DIR)/drivers/usb/misc/usbtest.ko $(call AddDepends/usb) endef define KernelPackage/usb-test/description Kernel support for testing USB Host Controller software endef $(eval $(call KernelPackage,usb-test)) define KernelPackage/usbip TITLE := USB-over-IP kernel support KCONFIG:= \ CONFIG_USBIP_CORE \ CONFIG_USBIP_DEBUG=n FILES:=$(LINUX_DIR)/drivers/usb/usbip/usbip-core.ko AUTOLOAD:=$(call AutoProbe,usbip-core) $(call AddDepends/usb) endef $(eval $(call KernelPackage,usbip)) define KernelPackage/usbip-client TITLE := USB-over-IP client driver DEPENDS := +kmod-usbip KCONFIG := CONFIG_USBIP_VHCI_HCD FILES :=$(LINUX_DIR)/drivers/usb/usbip/vhci-hcd.ko AUTOLOAD := $(call AutoProbe,vhci-hcd) $(call AddDepends/usb) endef $(eval $(call KernelPackage,usbip-client)) define KernelPackage/usbip-server $(call KernelPackage/usbip/Default) TITLE := USB-over-IP host driver DEPENDS := +kmod-usbip KCONFIG := CONFIG_USBIP_HOST FILES :=$(LINUX_DIR)/drivers/usb/usbip/usbip-host.ko AUTOLOAD := $(call AutoProbe,usbip-host) $(call AddDepends/usb) endef $(eval $(call KernelPackage,usbip-server)) define KernelPackage/usb-chipidea TITLE:=Host and device support for Chipidea controllers DEPENDS:=+USB_GADGET_SUPPORT:kmod-usb-gadget @TARGET_ar71xx||TARGET_ath79 +kmod-usb-ehci +kmod-usb-phy-nop KCONFIG:= \ CONFIG_EXTCON \ CONFIG_USB_CHIPIDEA \ CONFIG_USB_CHIPIDEA_HOST=y \ CONFIG_USB_CHIPIDEA_UDC=y \ CONFIG_USB_CHIPIDEA_DEBUG=y FILES:= \ $(LINUX_DIR)/drivers/extcon/extcon-core.ko \ $(LINUX_DIR)/drivers/usb/chipidea/ci_hdrc.ko \ $(LINUX_DIR)/drivers/usb/common/ulpi.ko@ge4.18 \ $(LINUX_DIR)/drivers/usb/roles/roles.ko@ge5.0 AUTOLOAD:=$(call AutoLoad,39,ci_hdrc,1) $(call AddDepends/usb) endef define KernelPackage/usb-chipidea/description Kernel support for USB Chipidea controllers endef $(eval $(call KernelPackage,usb-chipidea)) define KernelPackage/usb-chipidea2 TITLE:=Host and device support for Chipidea2 controllers DEPENDS:=+kmod-usb-chipidea KCONFIG:= \ CONFIG_EXTCON \ CONFIG_USB_CHIPIDEA \ CONFIG_USB_CHIPIDEA_HOST=y \ CONFIG_USB_CHIPIDEA_UDC=y \ CONFIG_USB_CHIPIDEA_DEBUG=y FILES:= \ $(LINUX_DIR)/drivers/extcon/extcon-core.ko \ $(LINUX_DIR)/drivers/usb/chipidea/ci_hdrc_usb2.ko AUTOLOAD:=$(call AutoLoad,39,ci_hdrc_usb2,1) $(call AddDepends/usb) endef define KernelPackage/usb-chipidea2/description Kernel support for USB Chipidea controllers endef $(eval $(call KernelPackage,usb-chipidea2)) define KernelPackage/usbmon TITLE:=USB traffic monitor KCONFIG:=CONFIG_USB_MON $(call AddDepends/usb) FILES:=$(LINUX_DIR)/drivers/usb/mon/usbmon.ko AUTOLOAD:=$(call AutoProbe,usbmon) endef define KernelPackage/usbmon/description Kernel support for USB traffic monitoring endef $(eval $(call KernelPackage,usbmon)) XHCI_MODULES := xhci-hcd xhci-pci xhci-plat-hcd ifdef CONFIG_TARGET_ramips_mt7621 XHCI_MODULES += xhci-mtk endif XHCI_FILES := $(wildcard $(patsubst %,$(LINUX_DIR)/drivers/usb/host/%.ko,$(XHCI_MODULES))) XHCI_AUTOLOAD := $(patsubst $(LINUX_DIR)/drivers/usb/host/%.ko,%,$(XHCI_FILES)) define KernelPackage/usb3 TITLE:=Support for USB3 controllers DEPENDS:= \ +TARGET_bcm53xx:kmod-usb-bcma \ +TARGET_bcm53xx:kmod-phy-bcm-ns-usb3 KCONFIG:= \ CONFIG_USB_PCI=y \ CONFIG_USB_XHCI_HCD \ CONFIG_USB_XHCI_PCI \ CONFIG_USB_XHCI_PLATFORM \ CONFIG_USB_XHCI_MTK \ CONFIG_USB_XHCI_HCD_DEBUGGING=n FILES:= \ $(XHCI_FILES) AUTOLOAD:=$(call AutoLoad,54,$(XHCI_AUTOLOAD),1) $(call AddDepends/usb) endef define KernelPackage/usb3/description Kernel support for USB3 (XHCI) controllers endef $(eval $(call KernelPackage,usb3)) define KernelPackage/usb-net2280 TITLE:=Support for NetChip 228x PCI USB peripheral controller KCONFIG:= \ CONFIG_USB_PCI=y \ CONFIG_USB_NET2280 DEPENDS:=@PCI_SUPPORT +kmod-usb-gadget FILES:=$(LINUX_DIR)/drivers/usb/gadget/udc/net2280.ko AUTOLOAD:=$(call AutoLoad,46,net2280) $(call AddDepends/usb) endef define KernelPackage/usb-net2280/description Kernel support for NetChip 228x / PLX USB338x PCI USB peripheral controller. endef $(eval $(call KernelPackage,usb-net2280)) define KernelPackage/chaoskey SUBMENU:=$(USB_MENU) TITLE:=Chaoskey hardware RNG support DEPENDS:=+kmod-random-core KCONFIG:=CONFIG_USB_CHAOSKEY FILES:=$(LINUX_DIR)/drivers/usb/misc/chaoskey.ko AUTOLOAD:=$(call AutoProbe,chaoskey) $(call AddDepends/usb) endef define KernelPackage/chaoskey/description Kernel module for chaoskey, USB attached true random number generator endef $(eval $(call KernelPackage,chaoskey))