diff options
author | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-28 22:23:06 -0500 |
commit | 47871889c601d8199c51a4086f77eebd77c29b0b (patch) | |
tree | 40cdcac3bff0ee40cc33dcca61d0577cdf965f77 /drivers/media/IR | |
parent | c16cc0b464b8876cfd57ce1c1dbcb6f9a6a0bce3 (diff) | |
parent | 30ff056c42c665b9ea535d8515890857ae382540 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
drivers/firmware/iscsi_ibft.c
Diffstat (limited to 'drivers/media/IR')
-rw-r--r-- | drivers/media/IR/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/IR/ir-functions.c | 2 | ||||
-rw-r--r-- | drivers/media/IR/ir-keymaps.c | 99 | ||||
-rw-r--r-- | drivers/media/IR/ir-keytable.c | 61 | ||||
-rw-r--r-- | drivers/media/IR/ir-sysfs.c | 211 |
5 files changed, 352 insertions, 23 deletions
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index df5ddb4bbbf7..171890e7a41d 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | ir-common-objs := ir-functions.o ir-keymaps.o | 1 | ir-common-objs := ir-functions.o ir-keymaps.o |
2 | ir-core-objs := ir-keytable.o | 2 | ir-core-objs := ir-keytable.o ir-sysfs.o |
3 | 3 | ||
4 | obj-$(CONFIG_IR_CORE) += ir-core.o | 4 | obj-$(CONFIG_IR_CORE) += ir-core.o |
5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o | 5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o |
diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index 776a136616d6..ab06919ad5fc 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c | |||
@@ -52,7 +52,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | |||
52 | /* -------------------------------------------------------------------------- */ | 52 | /* -------------------------------------------------------------------------- */ |
53 | 53 | ||
54 | int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | 54 | int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, |
55 | int ir_type) | 55 | const u64 ir_type) |
56 | { | 56 | { |
57 | ir->ir_type = ir_type; | 57 | ir->ir_type = ir_type; |
58 | 58 | ||
diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 9bbe6b1e9871..0efdefe75f32 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c | |||
@@ -3393,3 +3393,102 @@ struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { | |||
3393 | }; | 3393 | }; |
3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); | 3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); |
3395 | 3395 | ||
3396 | |||
3397 | /* Leadtek Winfast TV USB II Deluxe remote | ||
3398 | Magnus Alm <magnus.alm@gmail.com> | ||
3399 | */ | ||
3400 | static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { | ||
3401 | { 0x62, KEY_0}, | ||
3402 | { 0x75, KEY_1}, | ||
3403 | { 0x76, KEY_2}, | ||
3404 | { 0x77, KEY_3}, | ||
3405 | { 0x79, KEY_4}, | ||
3406 | { 0x7a, KEY_5}, | ||
3407 | { 0x7b, KEY_6}, | ||
3408 | { 0x7d, KEY_7}, | ||
3409 | { 0x7e, KEY_8}, | ||
3410 | { 0x7f, KEY_9}, | ||
3411 | |||
3412 | { 0x38, KEY_CAMERA}, /* SNAPSHOT */ | ||
3413 | { 0x37, KEY_RECORD}, /* RECORD */ | ||
3414 | { 0x35, KEY_TIME}, /* TIMESHIFT */ | ||
3415 | |||
3416 | { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
3417 | { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
3418 | { 0x64, KEY_MUTE}, /* MUTE */ | ||
3419 | |||
3420 | { 0x21, KEY_CHANNEL}, /* SURF */ | ||
3421 | { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ | ||
3422 | { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
3423 | { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ | ||
3424 | |||
3425 | { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ | ||
3426 | |||
3427 | { 0x70, KEY_POWER2}, /* TV ON/OFF */ | ||
3428 | |||
3429 | { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ | ||
3430 | { 0x3a, KEY_NEW}, /* PIP */ | ||
3431 | { 0x73, KEY_ZOOM}, /* FULLSECREEN */ | ||
3432 | |||
3433 | { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ | ||
3434 | |||
3435 | { 0x31, KEY_DOT}, /* '.' */ | ||
3436 | { 0x63, KEY_ENTER}, /* ENTER */ | ||
3437 | |||
3438 | }; | ||
3439 | struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table = { | ||
3440 | .scan = ir_codes_winfast_usbii_deluxe, | ||
3441 | .size = ARRAY_SIZE(ir_codes_winfast_usbii_deluxe), | ||
3442 | }; | ||
3443 | EXPORT_SYMBOL_GPL(ir_codes_winfast_usbii_deluxe_table); | ||
3444 | |||
3445 | /* Kworld 315U | ||
3446 | */ | ||
3447 | static struct ir_scancode ir_codes_kworld_315u[] = { | ||
3448 | { 0x6143, KEY_POWER }, | ||
3449 | { 0x6101, KEY_TUNER }, /* source */ | ||
3450 | { 0x610b, KEY_ZOOM }, | ||
3451 | { 0x6103, KEY_POWER2 }, /* shutdown */ | ||
3452 | |||
3453 | { 0x6104, KEY_1 }, | ||
3454 | { 0x6108, KEY_2 }, | ||
3455 | { 0x6102, KEY_3 }, | ||
3456 | { 0x6109, KEY_CHANNELUP }, | ||
3457 | |||
3458 | { 0x610f, KEY_4 }, | ||
3459 | { 0x6105, KEY_5 }, | ||
3460 | { 0x6106, KEY_6 }, | ||
3461 | { 0x6107, KEY_CHANNELDOWN }, | ||
3462 | |||
3463 | { 0x610c, KEY_7 }, | ||
3464 | { 0x610d, KEY_8 }, | ||
3465 | { 0x610a, KEY_9 }, | ||
3466 | { 0x610e, KEY_VOLUMEUP }, | ||
3467 | |||
3468 | { 0x6110, KEY_LAST }, | ||
3469 | { 0x6111, KEY_0 }, | ||
3470 | { 0x6112, KEY_ENTER }, | ||
3471 | { 0x6113, KEY_VOLUMEDOWN }, | ||
3472 | |||
3473 | { 0x6114, KEY_RECORD }, | ||
3474 | { 0x6115, KEY_STOP }, | ||
3475 | { 0x6116, KEY_PLAY }, | ||
3476 | { 0x6117, KEY_MUTE }, | ||
3477 | |||
3478 | { 0x6118, KEY_UP }, | ||
3479 | { 0x6119, KEY_DOWN }, | ||
3480 | { 0x611a, KEY_LEFT }, | ||
3481 | { 0x611b, KEY_RIGHT }, | ||
3482 | |||
3483 | { 0x611c, KEY_RED }, | ||
3484 | { 0x611d, KEY_GREEN }, | ||
3485 | { 0x611e, KEY_YELLOW }, | ||
3486 | { 0x611f, KEY_BLUE }, | ||
3487 | }; | ||
3488 | |||
3489 | struct ir_scancode_table ir_codes_kworld_315u_table = { | ||
3490 | .scan = ir_codes_kworld_315u, | ||
3491 | .size = ARRAY_SIZE(ir_codes_kworld_315u), | ||
3492 | .ir_type = IR_TYPE_NEC, | ||
3493 | }; | ||
3494 | EXPORT_SYMBOL_GPL(ir_codes_kworld_315u_table); | ||
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index b521ed9d6e2e..0903f539bf68 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -65,7 +65,7 @@ exit: | |||
65 | * In order to reduce the quantity of table resizes, it has a minimum | 65 | * In order to reduce the quantity of table resizes, it has a minimum |
66 | * table size of IR_TAB_MIN_SIZE. | 66 | * table size of IR_TAB_MIN_SIZE. |
67 | */ | 67 | */ |
68 | int ir_roundup_tablesize(int n_elems) | 68 | static int ir_roundup_tablesize(int n_elems) |
69 | { | 69 | { |
70 | size_t size; | 70 | size_t size; |
71 | 71 | ||
@@ -81,7 +81,6 @@ int ir_roundup_tablesize(int n_elems) | |||
81 | 81 | ||
82 | return n_elems; | 82 | return n_elems; |
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | ||
85 | 84 | ||
86 | /** | 85 | /** |
87 | * ir_copy_table() - copies a keytable, discarding the unused entries | 86 | * ir_copy_table() - copies a keytable, discarding the unused entries |
@@ -89,9 +88,11 @@ EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | |||
89 | * @origin: origin table | 88 | * @origin: origin table |
90 | * | 89 | * |
91 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED | 90 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED |
91 | * Also copies table size and table protocol. | ||
92 | * NOTE: It shouldn't copy the lock field | ||
92 | */ | 93 | */ |
93 | 94 | ||
94 | int ir_copy_table(struct ir_scancode_table *destin, | 95 | static int ir_copy_table(struct ir_scancode_table *destin, |
95 | const struct ir_scancode_table *origin) | 96 | const struct ir_scancode_table *origin) |
96 | { | 97 | { |
97 | int i, j = 0; | 98 | int i, j = 0; |
@@ -105,12 +106,12 @@ int ir_copy_table(struct ir_scancode_table *destin, | |||
105 | j++; | 106 | j++; |
106 | } | 107 | } |
107 | destin->size = j; | 108 | destin->size = j; |
109 | destin->ir_type = origin->ir_type; | ||
108 | 110 | ||
109 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); | 111 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); |
110 | 112 | ||
111 | return 0; | 113 | return 0; |
112 | } | 114 | } |
113 | EXPORT_SYMBOL_GPL(ir_copy_table); | ||
114 | 115 | ||
115 | /** | 116 | /** |
116 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table | 117 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table |
@@ -184,18 +185,14 @@ static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) | |||
184 | int newsize = rc_tab->size - 1; | 185 | int newsize = rc_tab->size - 1; |
185 | int resize = ir_is_resize_needed(rc_tab, newsize); | 186 | int resize = ir_is_resize_needed(rc_tab, newsize); |
186 | struct ir_scancode *oldkeymap = rc_tab->scan; | 187 | struct ir_scancode *oldkeymap = rc_tab->scan; |
187 | struct ir_scancode *newkeymap; | 188 | struct ir_scancode *newkeymap = NULL; |
188 | 189 | ||
189 | if (resize) { | 190 | if (resize) |
190 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * | 191 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * |
191 | sizeof(*newkeymap), GFP_ATOMIC); | 192 | sizeof(*newkeymap), GFP_ATOMIC); |
192 | 193 | ||
193 | /* There's no memory for resize. Keep the old table */ | 194 | /* There's no memory for resize. Keep the old table */ |
194 | if (!newkeymap) | 195 | if (!resize || !newkeymap) { |
195 | resize = 0; | ||
196 | } | ||
197 | |||
198 | if (!resize) { | ||
199 | newkeymap = oldkeymap; | 196 | newkeymap = oldkeymap; |
200 | 197 | ||
201 | /* We'll modify the live table. Lock it */ | 198 | /* We'll modify the live table. Lock it */ |
@@ -399,12 +396,14 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | |||
399 | * @input_dev: the struct input_dev descriptor of the device | 396 | * @input_dev: the struct input_dev descriptor of the device |
400 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | 397 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap |
401 | * | 398 | * |
402 | * This routine is used to initialize the input infrastructure to work with | 399 | * This routine is used to initialize the input infrastructure |
403 | * an IR. | 400 | * to work with an IR. |
404 | * It should be called before registering the IR device. | 401 | * It will register the input/evdev interface for the device and |
402 | * register the syfs code for IR class | ||
405 | */ | 403 | */ |
406 | int ir_input_register(struct input_dev *input_dev, | 404 | int ir_input_register(struct input_dev *input_dev, |
407 | struct ir_scancode_table *rc_tab) | 405 | const struct ir_scancode_table *rc_tab, |
406 | const struct ir_dev_props *props) | ||
408 | { | 407 | { |
409 | struct ir_input_dev *ir_dev; | 408 | struct ir_input_dev *ir_dev; |
410 | struct ir_scancode *keymap = rc_tab->scan; | 409 | struct ir_scancode *keymap = rc_tab->scan; |
@@ -417,19 +416,22 @@ int ir_input_register(struct input_dev *input_dev, | |||
417 | if (!ir_dev) | 416 | if (!ir_dev) |
418 | return -ENOMEM; | 417 | return -ENOMEM; |
419 | 418 | ||
420 | spin_lock_init(&rc_tab->lock); | 419 | spin_lock_init(&ir_dev->rc_tab.lock); |
421 | 420 | ||
422 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); | 421 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); |
423 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * | 422 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * |
424 | sizeof(struct ir_scancode), GFP_KERNEL); | 423 | sizeof(struct ir_scancode), GFP_KERNEL); |
425 | if (!ir_dev->rc_tab.scan) | 424 | if (!ir_dev->rc_tab.scan) { |
425 | kfree(ir_dev); | ||
426 | return -ENOMEM; | 426 | return -ENOMEM; |
427 | } | ||
427 | 428 | ||
428 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | 429 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", |
429 | ir_dev->rc_tab.size, | 430 | ir_dev->rc_tab.size, |
430 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); | 431 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); |
431 | 432 | ||
432 | ir_copy_table(&ir_dev->rc_tab, rc_tab); | 433 | ir_copy_table(&ir_dev->rc_tab, rc_tab); |
434 | ir_dev->props = props; | ||
433 | 435 | ||
434 | /* set the bits for the keys */ | 436 | /* set the bits for the keys */ |
435 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); | 437 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); |
@@ -447,16 +449,31 @@ int ir_input_register(struct input_dev *input_dev, | |||
447 | input_set_drvdata(input_dev, ir_dev); | 449 | input_set_drvdata(input_dev, ir_dev); |
448 | 450 | ||
449 | rc = input_register_device(input_dev); | 451 | rc = input_register_device(input_dev); |
452 | if (rc < 0) | ||
453 | goto err; | ||
454 | |||
455 | rc = ir_register_class(input_dev); | ||
450 | if (rc < 0) { | 456 | if (rc < 0) { |
451 | kfree(rc_tab->scan); | 457 | input_unregister_device(input_dev); |
452 | kfree(ir_dev); | 458 | goto err; |
453 | input_set_drvdata(input_dev, NULL); | ||
454 | } | 459 | } |
455 | 460 | ||
461 | return 0; | ||
462 | |||
463 | err: | ||
464 | kfree(rc_tab->scan); | ||
465 | kfree(ir_dev); | ||
466 | input_set_drvdata(input_dev, NULL); | ||
456 | return rc; | 467 | return rc; |
457 | } | 468 | } |
458 | EXPORT_SYMBOL_GPL(ir_input_register); | 469 | EXPORT_SYMBOL_GPL(ir_input_register); |
459 | 470 | ||
471 | /** | ||
472 | * ir_input_unregister() - unregisters IR and frees resources | ||
473 | * @input_dev: the struct input_dev descriptor of the device | ||
474 | |||
475 | * This routine is used to free memory and de-register interfaces. | ||
476 | */ | ||
460 | void ir_input_unregister(struct input_dev *dev) | 477 | void ir_input_unregister(struct input_dev *dev) |
461 | { | 478 | { |
462 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 479 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
@@ -472,6 +489,8 @@ void ir_input_unregister(struct input_dev *dev) | |||
472 | kfree(rc_tab->scan); | 489 | kfree(rc_tab->scan); |
473 | rc_tab->scan = NULL; | 490 | rc_tab->scan = NULL; |
474 | 491 | ||
492 | ir_unregister_class(dev); | ||
493 | |||
475 | kfree(ir_dev); | 494 | kfree(ir_dev); |
476 | input_unregister_device(dev); | 495 | input_unregister_device(dev); |
477 | } | 496 | } |
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c new file mode 100644 index 000000000000..bf5fbcd84238 --- /dev/null +++ b/drivers/media/IR/ir-sysfs.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* ir-register.c - handle IR scancode->keycode tables | ||
2 | * | ||
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/input.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <media/ir-core.h> | ||
18 | |||
19 | #define IRRCV_NUM_DEVICES 256 | ||
20 | |||
21 | /* bit array to represent IR sysfs device number */ | ||
22 | static unsigned long ir_core_dev_number; | ||
23 | |||
24 | /* class for /sys/class/irrcv */ | ||
25 | static struct class *ir_input_class; | ||
26 | |||
27 | /** | ||
28 | * show_protocol() - shows the current IR protocol | ||
29 | * @d: the device descriptor | ||
30 | * @mattr: the device attribute struct (unused) | ||
31 | * @buf: a pointer to the output buffer | ||
32 | * | ||
33 | * This routine is a callback routine for input read the IR protocol type. | ||
34 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | ||
35 | * It returns the protocol name, as understood by the driver. | ||
36 | */ | ||
37 | static ssize_t show_protocol(struct device *d, | ||
38 | struct device_attribute *mattr, char *buf) | ||
39 | { | ||
40 | char *s; | ||
41 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
42 | u64 ir_type = ir_dev->rc_tab.ir_type; | ||
43 | |||
44 | IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); | ||
45 | |||
46 | /* FIXME: doesn't support multiple protocols at the same time */ | ||
47 | if (ir_type == IR_TYPE_UNKNOWN) | ||
48 | s = "Unknown"; | ||
49 | else if (ir_type == IR_TYPE_RC5) | ||
50 | s = "RC-5"; | ||
51 | else if (ir_type == IR_TYPE_PD) | ||
52 | s = "Pulse/distance"; | ||
53 | else if (ir_type == IR_TYPE_NEC) | ||
54 | s = "NEC"; | ||
55 | else | ||
56 | s = "Other"; | ||
57 | |||
58 | return sprintf(buf, "%s\n", s); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * store_protocol() - shows the current IR protocol | ||
63 | * @d: the device descriptor | ||
64 | * @mattr: the device attribute struct (unused) | ||
65 | * @buf: a pointer to the input buffer | ||
66 | * @len: length of the input buffer | ||
67 | * | ||
68 | * This routine is a callback routine for changing the IR protocol type. | ||
69 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | ||
70 | * It changes the IR the protocol name, if the IR type is recognized | ||
71 | * by the driver. | ||
72 | * If an unknown protocol name is used, returns -EINVAL. | ||
73 | */ | ||
74 | static ssize_t store_protocol(struct device *d, | ||
75 | struct device_attribute *mattr, | ||
76 | const char *data, | ||
77 | size_t len) | ||
78 | { | ||
79 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
80 | u64 ir_type = IR_TYPE_UNKNOWN; | ||
81 | int rc = -EINVAL; | ||
82 | unsigned long flags; | ||
83 | char *buf; | ||
84 | |||
85 | buf = strsep((char **) &data, "\n"); | ||
86 | |||
87 | if (!strcasecmp(buf, "rc-5")) | ||
88 | ir_type = IR_TYPE_RC5; | ||
89 | else if (!strcasecmp(buf, "pd")) | ||
90 | ir_type = IR_TYPE_PD; | ||
91 | else if (!strcasecmp(buf, "nec")) | ||
92 | ir_type = IR_TYPE_NEC; | ||
93 | |||
94 | if (ir_type == IR_TYPE_UNKNOWN) { | ||
95 | IR_dprintk(1, "Error setting protocol to %lld\n", | ||
96 | (long long)ir_type); | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | if (ir_dev->props && ir_dev->props->change_protocol) | ||
101 | rc = ir_dev->props->change_protocol(ir_dev->props->priv, | ||
102 | ir_type); | ||
103 | |||
104 | if (rc < 0) { | ||
105 | IR_dprintk(1, "Error setting protocol to %lld\n", | ||
106 | (long long)ir_type); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); | ||
111 | ir_dev->rc_tab.ir_type = ir_type; | ||
112 | spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); | ||
113 | |||
114 | IR_dprintk(1, "Current protocol is %lld\n", | ||
115 | (long long)ir_type); | ||
116 | |||
117 | return len; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Static device attribute struct with the sysfs attributes for IR's | ||
122 | */ | ||
123 | static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, | ||
124 | show_protocol, store_protocol); | ||
125 | |||
126 | static struct attribute *ir_dev_attrs[] = { | ||
127 | &dev_attr_current_protocol.attr, | ||
128 | NULL, | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? | ||
133 | * @input_dev: the struct input_dev descriptor of the device | ||
134 | * | ||
135 | * This routine is used to register the syfs code for IR class | ||
136 | */ | ||
137 | int ir_register_class(struct input_dev *input_dev) | ||
138 | { | ||
139 | int rc; | ||
140 | struct kobject *kobj; | ||
141 | |||
142 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
143 | int devno = find_first_zero_bit(&ir_core_dev_number, | ||
144 | IRRCV_NUM_DEVICES); | ||
145 | |||
146 | if (unlikely(devno < 0)) | ||
147 | return devno; | ||
148 | |||
149 | ir_dev->attr.attrs = ir_dev_attrs; | ||
150 | ir_dev->class_dev = device_create(ir_input_class, NULL, | ||
151 | input_dev->dev.devt, ir_dev, | ||
152 | "irrcv%d", devno); | ||
153 | kobj = &ir_dev->class_dev->kobj; | ||
154 | |||
155 | printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj)); | ||
156 | rc = sysfs_create_group(kobj, &ir_dev->attr); | ||
157 | if (unlikely(rc < 0)) { | ||
158 | device_destroy(ir_input_class, input_dev->dev.devt); | ||
159 | return -ENOMEM; | ||
160 | } | ||
161 | |||
162 | ir_dev->devno = devno; | ||
163 | set_bit(devno, &ir_core_dev_number); | ||
164 | |||
165 | return 0; | ||
166 | }; | ||
167 | |||
168 | /** | ||
169 | * ir_unregister_class() - removes the sysfs for sysfs for | ||
170 | * /sys/class/irrcv/irrcv? | ||
171 | * @input_dev: the struct input_dev descriptor of the device | ||
172 | * | ||
173 | * This routine is used to unregister the syfs code for IR class | ||
174 | */ | ||
175 | void ir_unregister_class(struct input_dev *input_dev) | ||
176 | { | ||
177 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
178 | struct kobject *kobj; | ||
179 | |||
180 | clear_bit(ir_dev->devno, &ir_core_dev_number); | ||
181 | |||
182 | kobj = &ir_dev->class_dev->kobj; | ||
183 | |||
184 | sysfs_remove_group(kobj, &ir_dev->attr); | ||
185 | device_destroy(ir_input_class, input_dev->dev.devt); | ||
186 | |||
187 | kfree(ir_dev->attr.name); | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Init/exit code for the module. Basically, creates/removes /sys/class/irrcv | ||
192 | */ | ||
193 | |||
194 | static int __init ir_core_init(void) | ||
195 | { | ||
196 | ir_input_class = class_create(THIS_MODULE, "irrcv"); | ||
197 | if (IS_ERR(ir_input_class)) { | ||
198 | printk(KERN_ERR "ir_core: unable to register irrcv class\n"); | ||
199 | return PTR_ERR(ir_input_class); | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void __exit ir_core_exit(void) | ||
206 | { | ||
207 | class_destroy(ir_input_class); | ||
208 | } | ||
209 | |||
210 | module_init(ir_core_init); | ||
211 | module_exit(ir_core_exit); | ||