Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

lirc: added support for RaspberryPi GPIO #38

Closed
wants to merge 15 commits into from

9 participants

@ar0n

This branch adds lirc capability for a simple receiver/blaster connected to the gpio pins (Details described here: http://aron.ws/projects/lirc_rpi/). Because bcm2708 core support can't be found in the mainline kernel, my patch won't be applied there, but got a promise that when it does it will be applied.

For people who use the RPi for multimedia purposes this adds cheap IR capabilities.

@lp0

Could this use gpiolib instead of accessing the GPIO registers directly?

I have a driver in my branch that supports GPIO IRQs:
https://github.com/raspberrypi/linux/wiki/How-to-boot-using-device-tree

@ar0n

I didn't know about that, but of course it can! I will modify the code.

Thanks!

@alexbain

@lp0 Is it likely that this pull request will be merged if it's converted to gpiolib?

@ar0n Thanks for spending the time on this improvement!

@naicheben

push ... I also would like to see the driver in the kernel. It is really annoying to compile the kernel each time just to get the module back running after updating archlinuxarm. I don't mind if it uses GPIO directly. It's the only device I use on GPIO.

@cleverca22 cleverca22 Partialy convert lirc_rpi over to gpiolib, only the tx side
TX was completely non-functional when i started

TX appears valid when using a scope, but hasnt been tested with actual hardware yet, RX unchanged and untested
9c84b93
@cleverca22

ive started the libgpio conversion, ar0n#1

cleverca22 and others added some commits
@cleverca22 cleverca22 minor bug, it was starting out with the tx led solid on, and wouldnt …
…turn off till the first transmit
942785c
@cleverca22 cleverca22 Zxyzzy's fix from http://www.raspberrypi.org/phpBB3/viewtopic.php?p=1…
…30248#p130248

after reading the code, i can see how it would happen
if the code ends with a pulse and no space with hardware carrier or if the softcarrier ends on a high due to its lenght
75af4e7
@cleverca22 cleverca22 changed part of recieve over to libgpio
while testing to see if it sanely handled errors, i found that it leaves the io region mapped, causing it to lock itself out
fixed
d05f774
@cleverca22 cleverca22 untested changes to switch irq number over to the libgpio function 5a56f4d
@ar0n ar0n Merge pull request #1 from cleverca22/rpi-patches
Partialy convert lirc_rpi over to gpiolib, only the tx side
5d6beac
Aron Szabo add driver to lirc Makefile and kernel configuration f379d5a
Aron Szabo Merge branch 'rpi-patches' of git://github.com/raspberrypi/linux into…
… rpi-patches
0097900
@ar0n ar0n lirc_rpi: Changes to conform with coding style 351841e
@alexbain

What's the status of this pull request? Is the GPIO conversion complete at this point?

@cleverca22

last i heard, ar0n was going to finish it off, but the last commit is from 23 days ago
i could take a look at it in ~1week and see what works and whats left to do

@ar0n

For the receiver part, yes. The transmitter part still needs work to work with gpiolib. I have a working piece of code, but still need to clean it up / calibrate the output etc ... I wil ltry to finish this up next week.

@cleverca22

yeah, i noticed the carrier was off by ~2-3khz, but i didnt bother fixing it once i found out the problem was drive current

@alexbain
@naicheben
@naicheben

A month later, still not finished? What's the problem? Maybe th ecommunity can help?

@cleverca22

i'll see what i do today, ive still got the hardware infront of the tv, just need to rebuild the module and see whats left

Module.symvers is missing from the firmware repo (again), so i'll need to rebuild the whole kernel before i can test things
i'll leave an update later when i get everything compiled and tested

@cleverca22 cleverca22 purge all direct gpio access, the code is now purely libgpio based
some of the mask/unmask parts im not sure of, ive marked them with comments
everything seems to work, it can RX and TX normaly
02c4ee5
@cleverca22

ok, ive got a working version of the module with everything going thru the lib, no raw register access
cleverca22@02c4ee5

i'll check for any issues i saw mentioned, like the led being left on, or the carrier freq being off
edit: freq is dead on all the way from 20khz to 60khz
gpio pin is left LOW after transmit ends and after module unloads

whats left?, testing and code quality?

@ar0n

Wow cool, i didn't manage to finish it yet (had to work and finish my studies), but I will test your version today and report back.

@cleverca22

helps when you have no fixed work hours and no school to go to :)

@popcornmix
Owner

The patch looks reasonable, but I don't have any hardware to test this, so if a few people can confirm it works I can accept it.

@alexbain
@AndyPi

Hi,

Ive been hoping for this so had a go, it fails to compile with:

drivers/staging/media/lirc/lirc_rpi.c:32:26: fatal error: linux/sysdev.h: No such file or directory
compilation terminated.

seems to compile with the include commented out though !!

will continue to test

regards

Andy

@naicheben

The file sysdev.h must be in your kernel-sources. I have it in
/opt/raspberrypi/linux/include/linux/sysdev.h
where /opt/rsapberrypi is the folder, were I startet to download the kernel via git

@popcornmix
Owner

include/linux/sysdev.h is in my 3.2.27 kernel, but it was removed in 3.3 and so isn't there is 3.6.y.
We will be switching to 3.6.y in the future, so moving sysdev.h seems desirable.

@cleverca22

if it builds fine without it, then is it even needed?

it compiles fine against 3.2.27 with that commented out

@naicheben

I think you are right, The code does not seem to use any of the functions from sysdev.h
So we can just delete the include.

@naicheben

Compiles fine here. I can only test Input with XBMC (Raspbian) but it seems to do just fine. No trouble yet.

@AndyPi

Hi,

tested with my simple IR homebrew reciever and it seems to function well. Well done !

regards

Andy

@ar0n

Actually the modification have been made to the blasting part, the receiver worked well before cleverca22's latest patch. I've also tested it and it works.

@cleverca22

the receiver side went under some changes just recently, because it was enabling the IRQ somewhat manualy (direct registers)
i switched it over to the irqchip struct, but couldnt really find any docs, so i just read random source files thru-out the whole kernel

@AndyPi

Hi
yes its true, arons lirc patch has been working well as an ir receiver for ages - Ive been using it and am very grateful (thanks aron).

Im using Openelec and having to patch each time, which is a minor inconvenince particularly when linux version changes. So I am very pleased that you guys have made such efforts to get the lirc_rpi patch to a stage where it can be merged.

Thanks again,
regards

Andy

I understand that that there has been more change to the blaster side and that the receiver side has been working well for ages.

@esalgado

Hi guys!

Nice work, I'm going to an electronics shop tomorrow to get a IR Sensor and I will test.

By the way, cloning your repository and making "make menuconfig" the menu shows kernel 3.2.19! Is that right?

Thanks!

@cleverca22

yeah, it threw tons of merge conflicts when i tried to merge with the latest pi linux repo

i just copied the module out to its own dir, and built it fully stand-alone, like you normaly do for non-tree modules
against the official pi linux repo

@ar0n

I will merge it with the new kernel shortly... ;)

@ar0n ar0n Merge branch 'rpi-patches' of https://github.com/cleverca22/linux int…
…o rpi-patches

Conflicts:
	drivers/staging/lirc/lirc_rpi.c
cdb2b25
@naicheben

ehhhmmm and how is it with the 3.2.27+ kernel? And with this pull request? Couldn't this now be merged and closed?

@ar0n

I have actually merged it, but not yet pushed it, because I still need to see if there are no timing issues. I will push it up today ;).

@esalgado

Is the driver lirc_rpi.c the same one in the patch for lirc (http://aron.ws/projects/lirc_rpi/lirc_rpi-0.2.2.patch) ?

Trying to compile lirc with that patch fails due to
/home/pi/src/lirc/drivers/lirc_rpi/lirc_rpi.c:318:6: error: 'GPIO_BASE' undeclared (first use in this function)

When I substitute this one with the one in this page it builds fine...

@cleverca22

GPIO_BASE was part of the raw register access, which isnt cross-platform

the new libgpio code in the latest version should (in theory) work on any platform with the required features (1 input pin, 1 output pin, and rise/falling edge interupts)

much more likely that it may even make it into the official kernel branch

and yeah, they are the same file, the patch is just an older version

@ar0n

I will take that patch off, because it only causes confusion ... :/

@ar0n

@esalgado: I've updated the patch on my site.

@ar0n

I've tested the module with the new kernel and I think it's stable and ready to be merged. I have not modified anything functional in cleverca22's patch, just cosmetics so that it complies with the kernel coding style.

@esalgado

Works flawlessly!!! I tried this last version of the patch and tested with several remotes.

Thanks!

@popcornmix
Owner

This pull request seems to be for rpi-patches which is no longer used.
Can you submit a pull request against rpi-3.2.27 (ideally squashing the commits).

@perryflynn

The module works perfect.
Many thanks for this!

@ar0n

Closing this, #152

@ar0n ar0n closed this
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
@palosaari palosaari [media] dvb_usb_v2: replace Kernel userspace lock with wait queue
There was sync mutex which was held over userspace. That is very
wrong and could cause deadlock if different userspace process is
used to "unlock". Wait queue seems to be correct solution for
that kind of synchronizing issue so use it instead.
lock debug gives following bug report:
================================================
[ BUG: lock held when returning to user space! ]
3.9.0-rc1+ #38 Tainted: G           O
------------------------------------------------
tzap/4614 is leaving the kernel with locks still held!
1 lock held by tzap/4614:

Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
bdecbe4
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
Borislav Petkov x86: Improve the printout of the SMP bootup CPU table
As the new x86 CPU bootup printout format code maintainer, I am
taking immediate action to improve and clean (and thus indulge
my OCD) the reporting of the cores when coming up online.

Fix padding to a right-hand alignment, cleanup code and bind
reporting width to the max number of supported CPUs on the
system, like this:

 [    0.074509] smpboot: Booting Node   0, Processors:      #1  #2  #3  #4  #5  #6  #7 OK
 [    0.644008] smpboot: Booting Node   1, Processors:  #8  #9 #10 #11 #12 #13 #14 #15 OK
 [    1.245006] smpboot: Booting Node   2, Processors: #16 #17 #18 #19 #20 #21 #22 #23 OK
 [    1.864005] smpboot: Booting Node   3, Processors: #24 #25 #26 #27 #28 #29 #30 #31 OK
 [    2.489005] smpboot: Booting Node   4, Processors: #32 #33 #34 #35 #36 #37 #38 #39 OK
 [    3.093005] smpboot: Booting Node   5, Processors: #40 #41 #42 #43 #44 #45 #46 #47 OK
 [    3.698005] smpboot: Booting Node   6, Processors: #48 #49 #50 #51 #52 #53 #54 #55 OK
 [    4.304005] smpboot: Booting Node   7, Processors: #56 #57 #58 #59 #60 #61 #62 #63 OK
 [    4.961413] Brought up 64 CPUs

and this:

 [    0.072367] smpboot: Booting Node   0, Processors:    #1 #2 #3 #4 #5 #6 #7 OK
 [    0.686329] Brought up 8 CPUs

Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Libin <huawei.libin@huawei.com>
Cc: wangyijing@huawei.com
Cc: fenghua.yu@intel.com
Cc: guohanjun@huawei.com
Cc: paul.gortmaker@windriver.com
Link: http://lkml.kernel.org/r/20130927143554.GF4422@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
646e29a
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
Borislav Petkov x86/boot: Further compress CPUs bootup message
Turn it into (for example):

[    0.073380] x86: Booting SMP configuration:
[    0.074005] .... node   #0, CPUs:          #1   #2   #3   #4   #5   #6   #7
[    0.603005] .... node   #1, CPUs:     #8   #9  #10  #11  #12  #13  #14  #15
[    1.200005] .... node   #2, CPUs:    #16  #17  #18  #19  #20  #21  #22  #23
[    1.796005] .... node   #3, CPUs:    #24  #25  #26  #27  #28  #29  #30  #31
[    2.393005] .... node   #4, CPUs:    #32  #33  #34  #35  #36  #37  #38  #39
[    2.996005] .... node   #5, CPUs:    #40  #41  #42  #43  #44  #45  #46  #47
[    3.600005] .... node   #6, CPUs:    #48  #49  #50  #51  #52  #53  #54  #55
[    4.202005] .... node   #7, CPUs:    #56  #57  #58  #59  #60  #61  #62  #63
[    4.811005] .... node   #8, CPUs:    #64  #65  #66  #67  #68  #69  #70  #71
[    5.421006] .... node   #9, CPUs:    #72  #73  #74  #75  #76  #77  #78  #79
[    6.032005] .... node  #10, CPUs:    #80  #81  #82  #83  #84  #85  #86  #87
[    6.648006] .... node  #11, CPUs:    #88  #89  #90  #91  #92  #93  #94  #95
[    7.262005] .... node  #12, CPUs:    #96  #97  #98  #99 #100 #101 #102 #103
[    7.865005] .... node  #13, CPUs:   #104 #105 #106 #107 #108 #109 #110 #111
[    8.466005] .... node  #14, CPUs:   #112 #113 #114 #115 #116 #117 #118 #119
[    9.073006] .... node  #15, CPUs:   #120 #121 #122 #123 #124 #125 #126 #127
[    9.679901] x86: Booted up 16 nodes, 128 CPUs

and drop useless elements.

Change num_digits() to hpa's division-avoiding, cell-phone-typed
version which he went at great lengths and pains to submit on a
Saturday evening.

Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: huawei.libin@huawei.com
Cc: wangyijing@huawei.com
Cc: fenghua.yu@intel.com
Cc: guohanjun@huawei.com
Cc: paul.gortmaker@windriver.com
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20130930095624.GB16383@pd.tnic
Signed-off-by: Ingo Molnar <mingo@kernel.org>
a17bce4
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
@rostedt rostedt ftrace: Have control op function callback only trace when RCU is watc…
…hing

Dave Jones reported that trinity would be able to trigger the following
back trace:

 ===============================
 [ INFO: suspicious RCU usage. ]
 3.10.0-rc2+ #38 Not tainted
 -------------------------------
 include/linux/rcupdate.h:771 rcu_read_lock() used illegally while idle!
 other info that might help us debug this:

 RCU used illegally from idle CPU!  rcu_scheduler_active = 1, debug_locks = 0
 RCU used illegally from extended quiescent state!
 1 lock held by trinity-child1/18786:
  #0:  (rcu_read_lock){.+.+..}, at: [<ffffffff8113dd48>] __perf_event_overflow+0x108/0x310
 stack backtrace:
 CPU: 3 PID: 18786 Comm: trinity-child1 Not tainted 3.10.0-rc2+ #38
  0000000000000000 ffff88020767bac8 ffffffff816e2f6b ffff88020767baf8
  ffffffff810b5897 ffff88021de92520 0000000000000000 ffff88020767bbf8
  0000000000000000 ffff88020767bb78 ffffffff8113ded4 ffffffff8113dd48
 Call Trace:
  [<ffffffff816e2f6b>] dump_stack+0x19/0x1b
  [<ffffffff810b5897>] lockdep_rcu_suspicious+0xe7/0x120
  [<ffffffff8113ded4>] __perf_event_overflow+0x294/0x310
  [<ffffffff8113dd48>] ? __perf_event_overflow+0x108/0x310
  [<ffffffff81309289>] ? __const_udelay+0x29/0x30
  [<ffffffff81076054>] ? __rcu_read_unlock+0x54/0xa0
  [<ffffffff816f4000>] ? ftrace_call+0x5/0x2f
  [<ffffffff8113dfa1>] perf_swevent_overflow+0x51/0xe0
  [<ffffffff8113e08f>] perf_swevent_event+0x5f/0x90
  [<ffffffff8113e1c9>] perf_tp_event+0x109/0x4f0
  [<ffffffff8113e36f>] ? perf_tp_event+0x2af/0x4f0
  [<ffffffff81074630>] ? __rcu_read_lock+0x20/0x20
  [<ffffffff8112d79f>] perf_ftrace_function_call+0xbf/0xd0
  [<ffffffff8110e1e1>] ? ftrace_ops_control_func+0x181/0x210
  [<ffffffff81074630>] ? __rcu_read_lock+0x20/0x20
  [<ffffffff81100cae>] ? rcu_eqs_enter_common+0x5e/0x470
  [<ffffffff8110e1e1>] ftrace_ops_control_func+0x181/0x210
  [<ffffffff816f4000>] ftrace_call+0x5/0x2f
  [<ffffffff8110e229>] ? ftrace_ops_control_func+0x1c9/0x210
  [<ffffffff816f4000>] ? ftrace_call+0x5/0x2f
  [<ffffffff81074635>] ? debug_lockdep_rcu_enabled+0x5/0x40
  [<ffffffff81074635>] ? debug_lockdep_rcu_enabled+0x5/0x40
  [<ffffffff81100cae>] ? rcu_eqs_enter_common+0x5e/0x470
  [<ffffffff8110112a>] rcu_eqs_enter+0x6a/0xb0
  [<ffffffff81103673>] rcu_user_enter+0x13/0x20
  [<ffffffff8114541a>] user_enter+0x6a/0xd0
  [<ffffffff8100f6d8>] syscall_trace_leave+0x78/0x140
  [<ffffffff816f46af>] int_check_syscall_exit_work+0x34/0x3d
 ------------[ cut here ]------------

Perf uses rcu_read_lock() but as the function tracer can trace functions
even when RCU is not currently active, this makes the rcu_read_lock()
used by perf ineffective.

As perf is currently the only user of the ftrace_ops_control_func() and
perf is also the only function callback that actively uses rcu_read_lock(),
the quick fix is to prevent the ftrace_ops_control_func() from calling
its callbacks if RCU is not active.

With Paul's new "rcu_is_watching()" we can tell if RCU is active or not.

Reported-by: Dave Jones <davej@redhat.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
b5aa3a4
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
@lokeshvutla lokeshvutla crypto: omap-sham - Fix Polling mode for larger blocks
Command "tcrypt sec=1 mode=403" give the follwoing error for Polling
mode:
root@am335x-evm:/# insmod tcrypt.ko sec=1 mode=403
[...]

[  346.982754] test 15 ( 4096 byte blocks, 1024 bytes per update,   4 updates):   4352 opers/sec,  17825792 bytes/sec
[  347.992661] test 16 ( 4096 byte blocks, 4096 bytes per update,   1 updates):   7095 opers/sec,  29061120 bytes/sec
[  349.002667] test 17 ( 8192 byte blocks,   16 bytes per update, 512 updates):
[  349.010882] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[  349.020037] pgd = ddeac000
[  349.022884] [00000000] *pgd=9dcb4831, *pte=00000000, *ppte=00000000
[  349.029816] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
[  349.035482] Modules linked in: tcrypt(+)
[  349.039617] CPU: 0 PID: 1473 Comm: insmod Not tainted 3.12.4-01566-g6279006-dirty #38
[  349.047832] task: dda91540 ti: ddcd2000 task.ti: ddcd2000
[  349.053517] PC is at omap_sham_xmit_dma+0x6c/0x238
[  349.058544] LR is at omap_sham_xmit_dma+0x38/0x238
[  349.063570] pc : [<c04eb7cc>]    lr : [<c04eb798>]    psr: 20000013
[  349.063570] sp : ddcd3c78  ip : 00000000  fp : 9d8980b8
[  349.075610] r10: 00000000  r9 : 00000000  r8 : 00000000
[  349.081090] r7 : 00001000  r6 : dd898000  r5 : 00000040  r4 : ddb10550
[  349.087935] r3 : 00000004  r2 : 00000010  r1 : 53100080  r0 : 00000000
[  349.094783] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[  349.102268] Control: 10c5387d  Table: 9deac019  DAC: 00000015
[  349.108294] Process insmod (pid: 1473, stack limit = 0xddcd2248)

[...]

This is because polling_mode is not enabled for ctx without FLAGS_FINUP.

For polling mode the bufcnt is made 0 unconditionally. But it should be made 0
only if it is a final update or a total is not zero(This condition is similar
to what is done in DMA case). Because of this wrong hashes are produced.

Fixing the same.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
acef7b0
@swarren swarren referenced this pull request from a commit in swarren/linux-rpi
@pranith pranith powerpc: Wire up sys_bpf() syscall
This patch wires up the new syscall sys_bpf() on powerpc.

Passes the tests in samples/bpf:

    #0 add+sub+mul OK
    #1 unreachable OK
    #2 unreachable2 OK
    #3 out of range jump OK
    #4 out of range jump2 OK
    #5 test1 ld_imm64 OK
    #6 test2 ld_imm64 OK
    #7 test3 ld_imm64 OK
    #8 test4 ld_imm64 OK
    #9 test5 ld_imm64 OK
    #10 no bpf_exit OK
    #11 loop (back-edge) OK
    #12 loop2 (back-edge) OK
    #13 conditional loop OK
    #14 read uninitialized register OK
    #15 read invalid register OK
    #16 program doesn't init R0 before exit OK
    #17 stack out of bounds OK
    #18 invalid call insn1 OK
    #19 invalid call insn2 OK
    #20 invalid function call OK
    #21 uninitialized stack1 OK
    #22 uninitialized stack2 OK
    #23 check valid spill/fill OK
    #24 check corrupted spill/fill OK
    #25 invalid src register in STX OK
    #26 invalid dst register in STX OK
    #27 invalid dst register in ST OK
    #28 invalid src register in LDX OK
    #29 invalid dst register in LDX OK
    #30 junk insn OK
    #31 junk insn2 OK
    #32 junk insn3 OK
    #33 junk insn4 OK
    #34 junk insn5 OK
    #35 misaligned read from stack OK
    #36 invalid map_fd for function call OK
    #37 don't check return value before access OK
    #38 access memory with incorrect alignment OK
    #39 sometimes access memory with incorrect alignment OK
    #40 jump test 1 OK
    #41 jump test 2 OK
    #42 jump test 3 OK
    #43 jump test 4 OK

Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
[mpe: test using samples/bpf]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
fcbb539
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 16, 2012
  1. lirc: added support for RaspberryPi GPIO

    Aron Szabo authored
Commits on Aug 16, 2012
  1. @cleverca22

    Partialy convert lirc_rpi over to gpiolib, only the tx side

    cleverca22 authored
    TX was completely non-functional when i started
    
    TX appears valid when using a scope, but hasnt been tested with actual hardware yet, RX unchanged and untested
Commits on Aug 18, 2012
  1. @cleverca22

    minor bug, it was starting out with the tx led solid on, and wouldnt …

    cleverca22 authored
    …turn off till the first transmit
Commits on Aug 21, 2012
  1. @cleverca22

    Zxyzzy's fix from http://www.raspberrypi.org/phpBB3/viewtopic.php?p=1…

    cleverca22 authored
    …30248#p130248
    
    after reading the code, i can see how it would happen
    if the code ends with a pulse and no space with hardware carrier or if the softcarrier ends on a high due to its lenght
  2. @cleverca22

    changed part of recieve over to libgpio

    cleverca22 authored
    while testing to see if it sanely handled errors, i found that it leaves the io region mapped, causing it to lock itself out
    fixed
Commits on Aug 23, 2012
  1. @cleverca22
Commits on Aug 27, 2012
  1. @ar0n

    Merge pull request #1 from cleverca22/rpi-patches

    ar0n authored
    Partialy convert lirc_rpi over to gpiolib, only the tx side
Commits on Aug 29, 2012
  1. add driver to lirc Makefile and kernel configuration

    Aron Szabo authored
  2. Merge branch 'rpi-patches' of git://github.com/raspberrypi/linux into…

    Aron Szabo authored
    … rpi-patches
  3. @ar0n
Commits on Oct 27, 2012
  1. @cleverca22

    purge all direct gpio access, the code is now purely libgpio based

    cleverca22 authored
    some of the mask/unmask parts im not sure of, ive marked them with comments
    everything seems to work, it can RX and TX normaly
Commits on Oct 29, 2012
  1. @ar0n

    Merge branch 'rpi-patches' of https://github.com/cleverca22/linux int…

    ar0n authored
    …o rpi-patches
    
    Conflicts:
    	drivers/staging/lirc/lirc_rpi.c
Commits on Oct 31, 2012
  1. @ar0n
Commits on Nov 1, 2012
  1. @ar0n
  2. @ar0n

    changed a few debugging messages

    ar0n authored
This page is out of date. Refresh to see the latest.
View
6 drivers/staging/lirc/Kconfig
@@ -38,6 +38,12 @@ config LIRC_PARALLEL
help
Driver for Homebrew Parallel Port Receivers
+config LIRC_RPI
+ tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi"
+ depends on LIRC
+ help
+ Driver for Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi
+
config LIRC_SASEM
tristate "Sasem USB IR Remote"
depends on LIRC && USB
View
1  drivers/staging/lirc/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o
+obj-$(CONFIG_LIRC_RPI) += lirc_rpi.o
obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
View
687 drivers/staging/lirc/lirc_rpi.c
@@ -0,0 +1,687 @@
+/*
+ * lirc_rpi.c
+ *
+ * lirc_rpi - Device driver that records pulse- and pause-lengths
+ * (space-lengths) (just like the lirc_serial driver does)
+ * between GPIO interrupt events on the Raspberry Pi.
+ * Lots of code has been taken from the lirc_serial module,
+ * so I would like say thanks to the authors.
+ *
+ * Copyright (C) 2012 Aron Robert Szabo <aron@reon.hu>,
+ * Michael Bishop <cleverca22@gmail.com>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+#include <linux/gpio.h>
+
+#define LIRC_DRIVER_NAME "lirc_rpi"
+#define RBUF_LEN 256
+#define LIRC_TRANSMITTER_LATENCY 256
+
+#ifndef MAX_UDELAY_MS
+#define MAX_UDELAY_US 5000
+#else
+#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
+#endif
+
+#define dprintk(fmt, args...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
+ fmt, ## args); \
+ } while (0)
+
+/* module parameters */
+
+/* set the default GPIO input pin */
+static int gpio_in_pin = 18;
+/* set the default GPIO output pin */
+static int gpio_out_pin = 17;
+/* enable debugging messages */
+static int debug;
+/* -1 = auto, 0 = active high, 1 = active low */
+static int sense = -1;
+/* use softcarrier by default */
+static int softcarrier = 1;
+
+struct gpio_chip *gpiochip;
+struct irq_chip *irqchip;
+struct irq_data *irqdata;
+
+/* forward declarations */
+static long send_pulse(unsigned long length);
+static void send_space(long length);
+static void lirc_rpi_exit(void);
+
+int valid_gpio_pins[] = { 0, 1, 4, 8, 7, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23,
+ 24, 25 };
+
+static struct platform_device *lirc_rpi_dev;
+static struct timeval lasttv = { 0, 0 };
+static struct lirc_buffer rbuf;
+static spinlock_t lock;
+
+/* initialized/set in init_timing_params() */
+static unsigned int freq = 38000;
+static unsigned int duty_cycle = 50;
+static unsigned long period;
+static unsigned long pulse_width;
+static unsigned long space_width;
+
+static void safe_udelay(unsigned long usecs)
+{
+ while (usecs > MAX_UDELAY_US) {
+ udelay(MAX_UDELAY_US);
+ usecs -= MAX_UDELAY_US;
+ }
+ udelay(usecs);
+}
+
+static int init_timing_params(unsigned int new_duty_cycle,
+ unsigned int new_freq)
+{
+ /*
+ * period, pulse/space width are kept with 8 binary places -
+ * IE multiplied by 256.
+ */
+ if (256 * 1000000L / new_freq * new_duty_cycle / 100 <=
+ LIRC_TRANSMITTER_LATENCY)
+ return -EINVAL;
+ if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
+ LIRC_TRANSMITTER_LATENCY)
+ return -EINVAL;
+ duty_cycle = new_duty_cycle;
+ freq = new_freq;
+ period = 256 * 1000000L / freq;
+ pulse_width = period * duty_cycle / 100;
+ space_width = period - pulse_width;
+ dprintk("in init_timing_params, freq=%d pulse=%ld, "
+ "space=%ld\n", freq, pulse_width, space_width);
+ return 0;
+}
+
+static long send_pulse_softcarrier(unsigned long length)
+{
+ int flag;
+ unsigned long actual, target, d;
+
+ length <<= 8;
+
+ actual = 0; target = 0; flag = 0;
+ while (actual < length) {
+ if (flag) {
+ gpiochip->set(gpiochip, gpio_out_pin, 0);
+ target += space_width;
+ } else {
+ gpiochip->set(gpiochip, gpio_out_pin, 1);
+ target += pulse_width;
+ }
+ d = (target - actual -
+ LIRC_TRANSMITTER_LATENCY + 128) >> 8;
+ /*
+ * Note - we've checked in ioctl that the pulse/space
+ * widths are big enough so that d is > 0
+ */
+ udelay(d);
+ actual += (d << 8) + LIRC_TRANSMITTER_LATENCY;
+ flag = !flag;
+ }
+ return (actual-length) >> 8;
+}
+
+static long send_pulse(unsigned long length)
+{
+ if (length <= 0)
+ return 0;
+
+ if (softcarrier) {
+ return send_pulse_softcarrier(length);
+ } else {
+ gpiochip->set(gpiochip, gpio_out_pin, 1);
+ safe_udelay(length);
+ return 0;
+ }
+}
+
+static void send_space(long length)
+{
+ gpiochip->set(gpiochip, gpio_out_pin, 0);
+ if (length <= 0)
+ return;
+ safe_udelay(length);
+}
+
+static void rbwrite(int l)
+{
+ if (lirc_buffer_full(&rbuf)) {
+ /* no new signals will be accepted */
+ dprintk("Buffer overrun\n");
+ return;
+ }
+ lirc_buffer_write(&rbuf, (void *)&l);
+}
+
+static void frbwrite(int l)
+{
+ /* simple noise filter */
+ static int pulse, space;
+ static unsigned int ptr;
+
+ if (ptr > 0 && (l & PULSE_BIT)) {
+ pulse += l & PULSE_MASK;
+ if (pulse > 250) {
+ rbwrite(space);
+ rbwrite(pulse | PULSE_BIT);
+ ptr = 0;
+ pulse = 0;
+ }
+ return;
+ }
+ if (!(l & PULSE_BIT)) {
+ if (ptr == 0) {
+ if (l > 20000) {
+ space = l;
+ ptr++;
+ return;
+ }
+ } else {
+ if (l > 20000) {
+ space += pulse;
+ if (space > PULSE_MASK)
+ space = PULSE_MASK;
+ space += l;
+ if (space > PULSE_MASK)
+ space = PULSE_MASK;
+ pulse = 0;
+ return;
+ }
+ rbwrite(space);
+ rbwrite(pulse | PULSE_BIT);
+ ptr = 0;
+ pulse = 0;
+ }
+ }
+ rbwrite(l);
+}
+
+static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
+{
+ struct timeval tv;
+ long deltv;
+ int data;
+ int signal;
+
+ /* use the GPIO signal level */
+ signal = gpiochip->get(gpiochip, gpio_in_pin);
+
+ /* unmask the irq */
+ irqchip->irq_unmask(irqdata);
+
+ if (sense != -1) {
+ /* get current time */
+ do_gettimeofday(&tv);
+
+ /* calc time since last interrupt in microseconds */
+ deltv = tv.tv_sec-lasttv.tv_sec;
+ if (tv.tv_sec < lasttv.tv_sec ||
+ (tv.tv_sec == lasttv.tv_sec &&
+ tv.tv_usec < lasttv.tv_usec)) {
+ printk(KERN_WARNING LIRC_DRIVER_NAME
+ ": AIEEEE: your clock just jumped backwards\n");
+ printk(KERN_WARNING LIRC_DRIVER_NAME
+ ": %d %d %lx %lx %lx %lx\n", signal, sense,
+ tv.tv_sec, lasttv.tv_sec,
+ tv.tv_usec, lasttv.tv_usec);
+ data = PULSE_MASK;
+ } else if (deltv > 15) {
+ data = PULSE_MASK; /* really long time */
+ if (!(signal^sense)) {
+ /* sanity check */
+ printk(KERN_WARNING LIRC_DRIVER_NAME
+ ": AIEEEE: %d %d %lx %lx %lx %lx\n",
+ signal, sense, tv.tv_sec, lasttv.tv_sec,
+ tv.tv_usec, lasttv.tv_usec);
+ /*
+ * detecting pulse while this
+ * MUST be a space!
+ */
+ sense = sense ? 0 : 1;
+ }
+ } else {
+ data = (int) (deltv*1000000 +
+ (tv.tv_usec - lasttv.tv_usec));
+ }
+ frbwrite(signal^sense ? data : (data|PULSE_BIT));
+ lasttv = tv;
+ wake_up_interruptible(&rbuf.wait_poll);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int is_right_chip(struct gpio_chip *chip, void *data)
+{
+ dprintk("is_right_chip %s %d\n", chip->label, strcmp(data, chip->label));
+
+ if (strcmp(data, chip->label) == 0)
+ return 1;
+ return 0;
+}
+
+static int init_port(void)
+{
+ int i, nlow, nhigh, ret, irq;
+
+ gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
+
+ if (!gpiochip)
+ return -ENODEV;
+
+ if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
+ printk(KERN_ALERT LIRC_DRIVER_NAME
+ ": cant claim gpio pin %d\n", gpio_out_pin);
+ ret = -ENODEV;
+ goto exit_init_port;
+ }
+
+ if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
+ printk(KERN_ALERT LIRC_DRIVER_NAME
+ ": cant claim gpio pin %d\n", gpio_in_pin);
+ ret = -ENODEV;
+ goto exit_gpio_free_out_pin;
+ }
+
+ gpiochip->direction_input(gpiochip, gpio_in_pin);
+ gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
+ gpiochip->set(gpiochip, gpio_out_pin, 0);
+
+ irq = gpiochip->to_irq(gpiochip, gpio_in_pin);
+ dprintk("to_irq %d\n", irq);
+ irqdata = irq_get_irq_data(irq);
+
+ if (irqdata && irqdata->chip) {
+ irqchip = irqdata->chip;
+ } else {
+ ret = -ENODEV;
+ goto exit_gpio_free_in_pin;
+ }
+
+ /* if pin is high, then this must be an active low receiver. */
+ if (sense == -1) {
+ /* wait 1/2 sec for the power supply */
+ msleep(500);
+
+ /*
+ * probe 9 times every 0.04s, collect "votes" for
+ * active high/low
+ */
+ nlow = 0;
+ nhigh = 0;
+ for (i = 0; i < 9; i++) {
+ if (gpiochip->get(gpiochip, gpio_in_pin))
+ nlow++;
+ else
+ nhigh++;
+ msleep(40);
+ }
+ sense = (nlow >= nhigh ? 1 : 0);
+ printk(KERN_INFO LIRC_DRIVER_NAME
+ ": auto-detected active %s receiver on GPIO pin %d\n",
+ sense ? "low" : "high", gpio_in_pin);
+ } else {
+ printk(KERN_INFO LIRC_DRIVER_NAME
+ ": manually using active %s receiver on GPIO pin %d\n",
+ sense ? "low" : "high", gpio_in_pin);
+ }
+
+ return 0;
+
+ exit_gpio_free_in_pin:
+ gpio_free(gpio_in_pin);
+
+ exit_gpio_free_out_pin:
+ gpio_free(gpio_out_pin);
+
+ exit_init_port:
+ return ret;
+}
+
+// called when the character device is opened
+static int set_use_inc(void *data)
+{
+ int result;
+ unsigned long flags;
+
+ /* initialize timestamp */
+ do_gettimeofday(&lasttv);
+
+ result = request_irq(gpiochip->to_irq(gpiochip, gpio_in_pin),
+ (irq_handler_t) irq_handler, 0,
+ LIRC_DRIVER_NAME, (void*) 0);
+
+ switch (result) {
+ case -EBUSY:
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": IRQ %d is busy\n",
+ gpiochip->to_irq(gpiochip, gpio_in_pin));
+ return -EBUSY;
+ case -EINVAL:
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": Bad irq number or handler\n");
+ return -EINVAL;
+ default:
+ dprintk("Interrupt %d obtained\n",
+ gpiochip->to_irq(gpiochip, gpio_in_pin));
+ break;
+ };
+
+ /* initialize pulse/space widths */
+ init_timing_params(duty_cycle, freq);
+
+ spin_lock_irqsave(&lock, flags);
+
+ /* GPIO Pin Falling/Rising Edge Detect Enable */
+ irqchip->irq_set_type(irqdata,
+ IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING);
+
+ /* unmask the irq */
+ irqchip->irq_unmask(irqdata);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ return 0;
+}
+
+static void set_use_dec(void *data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&lock, flags);
+
+ /* GPIO Pin Falling/Rising Edge Detect Disable */
+ irqchip->irq_set_type(irqdata, 0);
+ irqchip->irq_mask(irqdata);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ free_irq(gpiochip->to_irq(gpiochip, gpio_in_pin), (void *) 0);
+
+ dprintk(KERN_INFO LIRC_DRIVER_NAME
+ ": freed IRQ %d\n", gpiochip->to_irq(gpiochip, gpio_in_pin));
+}
+
+static ssize_t lirc_write(struct file *file, const char *buf,
+ size_t n, loff_t *ppos)
+{
+ int i, count;
+ unsigned long flags;
+ long delta = 0;
+ int *wbuf;
+
+ count = n / sizeof(int);
+ if (n % sizeof(int) || count % 2 == 0)
+ return -EINVAL;
+ wbuf = memdup_user(buf, n);
+ if (IS_ERR(wbuf))
+ return PTR_ERR(wbuf);
+ spin_lock_irqsave(&lock, flags);
+
+ for (i = 0; i < count; i++) {
+ if (i%2)
+ send_space(wbuf[i] - delta);
+ else
+ delta = send_pulse(wbuf[i]);
+ }
+ gpiochip->set(gpiochip, gpio_out_pin, 0);
+
+ spin_unlock_irqrestore(&lock, flags);
+ kfree(wbuf);
+ return n;
+}
+
+static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+ int result;
+ __u32 value;
+
+ switch (cmd) {
+ case LIRC_GET_SEND_MODE:
+ return -ENOIOCTLCMD;
+ break;
+
+ case LIRC_SET_SEND_MODE:
+ result = get_user(value, (__u32 *) arg);
+ if (result)
+ return result;
+ /* only LIRC_MODE_PULSE supported */
+ if (value != LIRC_MODE_PULSE)
+ return -ENOSYS;
+ break;
+
+ case LIRC_GET_LENGTH:
+ return -ENOSYS;
+ break;
+
+ case LIRC_SET_SEND_DUTY_CYCLE:
+ dprintk("SET_SEND_DUTY_CYCLE\n");
+ result = get_user(value, (__u32 *) arg);
+ if (result)
+ return result;
+ if (value <= 0 || value > 100)
+ return -EINVAL;
+ return init_timing_params(value, freq);
+ break;
+
+ case LIRC_SET_SEND_CARRIER:
+ dprintk("SET_SEND_CARRIER\n");
+ result = get_user(value, (__u32 *) arg);
+ if (result)
+ return result;
+ if (value > 500000 || value < 20000)
+ return -EINVAL;
+ return init_timing_params(duty_cycle, value);
+ break;
+
+ default:
+ return lirc_dev_fop_ioctl(filep, cmd, arg);
+ }
+ return 0;
+}
+
+static const struct file_operations lirc_fops = {
+ .owner = THIS_MODULE,
+ .write = lirc_write,
+ .unlocked_ioctl = lirc_ioctl,
+ .read = lirc_dev_fop_read,
+ .poll = lirc_dev_fop_poll,
+ .open = lirc_dev_fop_open,
+ .release = lirc_dev_fop_close,
+ .llseek = no_llseek,
+};
+
+static struct lirc_driver driver = {
+ .name = LIRC_DRIVER_NAME,
+ .minor = -1,
+ .code_length = 1,
+ .sample_rate = 0,
+ .data = NULL,
+ .add_to_buf = NULL,
+ .rbuf = &rbuf,
+ .set_use_inc = set_use_inc,
+ .set_use_dec = set_use_dec,
+ .fops = &lirc_fops,
+ .dev = NULL,
+ .owner = THIS_MODULE,
+};
+
+static struct platform_driver lirc_rpi_driver = {
+ .driver = {
+ .name = LIRC_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init lirc_rpi_init(void)
+{
+ int result;
+
+ /* Init read buffer. */
+ result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
+ if (result < 0)
+ return -ENOMEM;
+
+ result = platform_driver_register(&lirc_rpi_driver);
+ if (result) {
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": lirc register returned %d\n", result);
+ goto exit_buffer_free;
+ }
+
+ lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
+ if (!lirc_rpi_dev) {
+ result = -ENOMEM;
+ goto exit_driver_unregister;
+ }
+
+ result = platform_device_add(lirc_rpi_dev);
+ if (result)
+ goto exit_device_put;
+
+ return 0;
+
+ exit_device_put:
+ platform_device_put(lirc_rpi_dev);
+
+ exit_driver_unregister:
+ platform_driver_unregister(&lirc_rpi_driver);
+
+ exit_buffer_free:
+ lirc_buffer_free(&rbuf);
+
+ return result;
+}
+
+static void lirc_rpi_exit(void)
+{
+ gpio_free(gpio_out_pin);
+ gpio_free(gpio_in_pin);
+ platform_device_unregister(lirc_rpi_dev);
+ platform_driver_unregister(&lirc_rpi_driver);
+ lirc_buffer_free(&rbuf);
+}
+
+static int __init lirc_rpi_init_module(void)
+{
+ int result, i;
+
+ result = lirc_rpi_init();
+ if (result)
+ return result;
+
+ /* check if the module received valid gpio pin numbers */
+ result = 0;
+ if (gpio_in_pin != gpio_out_pin) {
+ for(i = 0; (i < ARRAY_SIZE(valid_gpio_pins)) && (result != 2); i++) {
+ if (gpio_in_pin == valid_gpio_pins[i] ||
+ gpio_out_pin == valid_gpio_pins[i]) {
+ result++;
+ }
+ }
+ }
+
+ if (result != 2) {
+ result = -EINVAL;
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": invalid GPIO pin(s) specified!\n");
+ goto exit_rpi;
+ }
+
+ driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |
+ LIRC_CAN_SET_SEND_CARRIER |
+ LIRC_CAN_SEND_PULSE |
+ LIRC_CAN_REC_MODE2;
+
+ driver.dev = &lirc_rpi_dev->dev;
+ driver.minor = lirc_register_driver(&driver);
+
+ if (driver.minor < 0) {
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": device registration failed with %d\n", result);
+ result = -EIO;
+ goto exit_rpi;
+ }
+
+ printk(KERN_INFO LIRC_DRIVER_NAME ": driver registered!\n");
+
+ result = init_port();
+ if (result < 0)
+ goto exit_rpi;
+
+ return 0;
+
+ exit_rpi:
+ lirc_rpi_exit();
+
+ return result;
+}
+
+static void __exit lirc_rpi_exit_module(void)
+{
+ lirc_rpi_exit();
+
+ lirc_unregister_driver(driver.minor);
+ printk(KERN_INFO LIRC_DRIVER_NAME ": cleaned up module\n");
+}
+
+module_init(lirc_rpi_init_module);
+module_exit(lirc_rpi_exit_module);
+
+MODULE_DESCRIPTION("Infra-red receiver and blaster driver for Raspberry Pi GPIO.");
+MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");
+MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");
+MODULE_LICENSE("GPL");
+
+module_param(gpio_out_pin, int, S_IRUGO);
+MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"
+ " processor. Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11,"
+ " 14, 15, 17, 18, 21, 22, 23, 24, 25, default 17");
+
+module_param(gpio_in_pin, int, S_IRUGO);
+MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."
+ " Valid pin numbers are: 0, 1, 4, 8, 7, 9, 10, 11, 14, 15,"
+ " 17, 18, 21, 22, 23, 24, 25, default 18");
+
+module_param(sense, bool, S_IRUGO);
+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
+ " (0 = active high, 1 = active low )");
+
+module_param(softcarrier, bool, S_IRUGO);
+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
Something went wrong with that request. Please try again.