/* fetch serial input packet (1 byte) from register offset */ static u8 sinp(int offset)
{ if (iommap) /* the register is memory-mapped */
offset <<= ioshift;
return inb(io + offset);
}
/* write serial output packet (1 byte) of value to register offset */ staticvoid soutp(int offset, u8 value)
{ if (iommap) /* the register is memory-mapped */
offset <<= ioshift;
staticvoid send_pulse_irdeo(unsignedint length, ktime_t target)
{ long rawbits; int i; unsignedchar output; unsignedchar chunk, shifted;
/* how many bits have to be sent ? */
rawbits = length * 1152 / 10000; if (serial_ir.duty_cycle > 50)
chunk = 3; else
chunk = 1; for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
shifted = chunk << (i * 3);
shifted >>= 1;
output &= (~shifted);
i++; if (i == 3) {
soutp(UART_TX, output); while (!(sinp(UART_LSR) & UART_LSR_THRE))
;
output = 0x7f;
i = 0;
}
} if (i != 0) {
soutp(UART_TX, output); while (!(sinp(UART_LSR) & UART_LSR_TEMT))
;
}
}
staticvoid send_space_irdeo(void)
{
}
#ifdef CONFIG_IR_SERIAL_TRANSMITTER staticvoid send_pulse_homebrew_softcarrier(unsignedint length, ktime_t edge)
{
ktime_t now, target = ktime_add_us(edge, length); /* * delta should never exceed 4 seconds and on m68k * ndelay(s64) does not compile; so use s32 rather than s64.
*/
s32 delta; unsignedint pulse, space;
/* Ensure the dividend fits into 32 bit */
pulse = DIV_ROUND_CLOSEST(serial_ir.duty_cycle * (NSEC_PER_SEC / 100),
serial_ir.carrier);
space = DIV_ROUND_CLOSEST((100 - serial_ir.duty_cycle) *
(NSEC_PER_SEC / 100), serial_ir.carrier);
for (;;) {
now = ktime_get(); if (ktime_compare(now, target) >= 0) break;
on();
edge = ktime_add_ns(edge, pulse);
delta = ktime_to_ns(ktime_sub(edge, now)); if (delta > 0)
ndelay(delta);
now = ktime_get();
off(); if (ktime_compare(now, target) >= 0) break;
edge = ktime_add_ns(edge, space);
delta = ktime_to_ns(ktime_sub(edge, now)); if (delta > 0)
ndelay(delta);
}
}
if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { /* not our interrupt */ return IRQ_NONE;
}
counter = 0; do {
counter++;
status = sinp(UART_MSR); if (counter > RS_ISR_PASS_LIMIT) {
dev_err(&serial_ir.pdev->dev, "Trapped in interrupt"); break;
} if ((status & hardware[type].signal_pin_change) &&
sense != -1) { /* get current time */
kt = ktime_get();
/* * The driver needs to know if your receiver is * active high or active low, or the space/pulse * sense could be inverted.
*/
/* calc time since last interrupt in nanoseconds */
dcd = (status & hardware[type].signal_pin) ? 1 : 0;
staticint serial_ir_probe(struct platform_device *dev)
{ struct rc_dev *rcdev; int i, nlow, nhigh, result;
rcdev = devm_rc_allocate_device(&dev->dev, RC_DRIVER_IR_RAW); if (!rcdev) return -ENOMEM;
if (hardware[type].send_pulse && hardware[type].send_space)
rcdev->tx_ir = serial_ir_tx; if (hardware[type].set_send_carrier)
rcdev->s_tx_carrier = serial_ir_tx_carrier; if (hardware[type].set_duty_cycle)
rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
switch (type) { case IR_HOMEBREW:
rcdev->device_name = "Serial IR type home-brew"; break; case IR_IRDEO:
rcdev->device_name = "Serial IR type IRdeo"; break; case IR_IRDEO_REMOTE:
rcdev->device_name = "Serial IR type IRdeo remote"; break; case IR_ANIMAX:
rcdev->device_name = "Serial IR type AnimaX"; break; case IR_IGOR:
rcdev->device_name = "Serial IR type IgorPlug"; break;
}
/* 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 (sinp(UART_MSR) & hardware[type].signal_pin)
nlow++; else
nhigh++;
msleep(40);
}
sense = nlow >= nhigh ? 1 : 0;
dev_info(&dev->dev, "auto-detected active %s receiver\n",
sense ? "low" : "high");
} else
dev_info(&dev->dev, "Manually using active %s receiver\n",
sense ? "low" : "high");
dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
MODULE_DESCRIPTION("Infra-red receiver driver for serial ports.");
MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, Christoph Bartelmus, Andrei Tanas");
MODULE_LICENSE("GPL");
module_param_hw(io, int, ioport, 0444);
MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
/* some architectures (e.g. intel xscale) have memory mapped registers */
module_param_hw(iommap, ulong, other, 0444);
MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory mapped io)");
/* * some architectures (e.g. intel xscale) align the 8bit serial registers * on 32bit word boundaries. * See linux-kernel/drivers/tty/serial/8250/8250.c serial_in()/out()
*/
module_param_hw(ioshift, int, other, 0444);
MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
module_param_hw(irq, int, irq, 0444);
MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.