📄 lirc_sir.c
字号:
TC35143_IODIR_OUTPUT); ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH); } return 0;}#endifstatic int init_hardware(void){ int flags; spin_lock_irqsave(&hardware_lock, flags); /* reset UART */#ifdef LIRC_ON_SA1100#ifdef CONFIG_SA1100_BITSY if (machine_is_bitsy()) { printk("Power on IR module\n"); set_bitsy_egpio(EGPIO_BITSY_IR_ON); }#endif#ifdef CONFIG_SA1100_COLLIE sa1100_irda_set_power_collie(3); /* power on */#endif sr.hscr0=Ser2HSCR0; sr.utcr0=Ser2UTCR0; sr.utcr1=Ser2UTCR1; sr.utcr2=Ser2UTCR2; sr.utcr3=Ser2UTCR3; sr.utcr4=Ser2UTCR4; sr.utdr=Ser2UTDR; sr.utsr0=Ser2UTSR0; sr.utsr1=Ser2UTSR1; /* configure GPIO */ /* output */ PPDR|=PPC_TXD2; PSDR|=PPC_TXD2; /* set output to 0 */ off(); /* * Enable HP-SIR modulation, and ensure that the port is disabled. */ Ser2UTCR3=0; Ser2HSCR0=sr.hscr0 & (~HSCR0_HSSP); /* clear status register to prevent unwanted interrupts */ Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); /* 7N1 */ Ser2UTCR0=UTCR0_1StpBit|UTCR0_7BitData; /* 115200 */ Ser2UTCR1=0; Ser2UTCR2=1; /* use HPSIR, 1.6 usec pulses */ Ser2UTCR4=UTCR4_HPSIR|UTCR4_Z1_6us; /* enable receiver, receive fifo interrupt */ Ser2UTCR3=UTCR3_RXE|UTCR3_RIE; /* clear status register to prevent unwanted interrupts */ Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); #elif defined(LIRC_SIR_TEKRAM) /* disable FIFO */ soutp(UART_FCR, UART_FCR_CLEAR_RCVR| UART_FCR_CLEAR_XMIT| UART_FCR_TRIGGER_1); /* Set DLAB 0. */ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); /* First of all, disable all interrupts */ soutp(UART_IER, sinp(UART_IER)& (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); /* Set DLAB 1. */ soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); /* Set divisor to 12 => 9600 Baud */ soutp(UART_DLM,0); soutp(UART_DLL,12); /* Set DLAB 0. */ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); /* power supply */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); safe_udelay(50*1000); /* -DTR low -> reset PIC */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); udelay(1*1000); soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); udelay(100); /* -RTS low -> send control byte */ soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); udelay(7); soutp(UART_TX, TEKRAM_115200|TEKRAM_PW); /* one byte takes ~1042 usec to transmit at 9600,8N1 */ udelay(1500); /* back to normal operation */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); udelay(50); udelay(1500); /* read previous control byte */ printk(KERN_INFO LIRC_DRIVER_NAME ": 0x%02x\n",sinp(UART_RX)); /* Set DLAB 1. */ soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); /* Set divisor to 1 => 115200 Baud */ soutp(UART_DLM,0); soutp(UART_DLL,1); /* Set DLAB 0, 8 Bit */ soutp(UART_LCR, UART_LCR_WLEN8); /* enable interrupts */ soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);#else outb(0, io + UART_MCR); outb(0, io + UART_IER); /* init UART */ /* set DLAB, speed = 115200 */ outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); outb(1, io + UART_DLL); outb(0, io + UART_DLM); /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ outb(UART_LCR_WLEN7, io + UART_LCR); /* FIFO operation */ outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); /* interrupts */ // outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); outb(UART_IER_RDI, io + UART_IER); /* turn on UART */ outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR);#ifdef LIRC_SIR_ACTISYS_ACT200L init_act200();#endif#endif spin_unlock_irqrestore(&hardware_lock, flags); return 0;}static void drop_hardware(void){ int flags; spin_lock_irqsave(&hardware_lock, flags);#ifdef LIRC_ON_SA1100 Ser2UTCR3=0; Ser2UTCR0=sr.utcr0; Ser2UTCR1=sr.utcr1; Ser2UTCR2=sr.utcr2; Ser2UTCR4=sr.utcr4; Ser2UTCR3=sr.utcr3; Ser2HSCR0=sr.hscr0;#ifdef CONFIG_SA1100_BITSY if (machine_is_bitsy()) { clr_bitsy_egpio(EGPIO_BITSY_IR_ON); }#endif#ifdef CONFIG_SA1100_COLLIE sa1100_irda_set_power_collie(0); /* power off */#endif#else /* turn off interrupts */ outb(0, io + UART_IER); #endif spin_unlock_irqrestore(&hardware_lock, flags);}/* SECTION: Initialisation */static int init_port(void){ int retval; #ifndef LIRC_ON_SA1100 /* get I/O port access and IRQ line */ retval = check_region(io, 8); if (retval < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": i/o port 0x%.4x already in use.\n", io); return retval; }#endif retval = request_irq(irq, sir_interrupt, SA_INTERRUPT, LIRC_DRIVER_NAME, NULL); if (retval < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d already in use.\n", irq); return retval; }#ifndef LIRC_ON_SA1100 request_region(io, 8, LIRC_DRIVER_NAME); printk(KERN_INFO LIRC_DRIVER_NAME ": I/O port 0x%.4x, IRQ %d.\n", io, irq);#endif init_timer(&timerlist); timerlist.function = sir_timeout; timerlist.data = 0xabadcafe; return 0;}static void drop_port(void){ disable_irq(irq); free_irq(irq, NULL);#ifdef KERNEL_2_3 del_timer_sync(&timerlist);#else start_bh_atomic(); del_timer(&timerlist); end_bh_atomic();#endif#ifndef LIRC_ON_SA1100 release_region(io, 8);#endif}#ifdef LIRC_SIR_ACTISYS_ACT200L/******************************************************//* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle *//* some code borrowed from Linux IRDA driver *//* Regsiter 0: Control register #1 */#define ACT200L_REG0 0x00#define ACT200L_TXEN 0x01 /* Enable transmitter */#define ACT200L_RXEN 0x02 /* Enable receiver */#define ACT200L_ECHO 0x08 /* Echo control chars *//* Register 1: Control register #2 */#define ACT200L_REG1 0x10#define ACT200L_LODB 0x01 /* Load new baud rate count value */#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse *//* Register 3: Transmit mode register #2 */#define ACT200L_REG3 0x30#define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */#define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */#define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit *//* Register 4: Output Power register */#define ACT200L_REG4 0x40#define ACT200L_OP0 0x01 /* Enable LED1C output */#define ACT200L_OP1 0x02 /* Enable LED2C output */#define ACT200L_BLKR 0x04/* Register 5: Receive Mode register */#define ACT200L_REG5 0x50#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */ /*.. other various IRDA bit modes, and TV remote modes..*//* Register 6: Receive Sensitivity register #1 */#define ACT200L_REG6 0x60#define ACT200L_RS0 0x01 /* receive threshold bit 0 */#define ACT200L_RS1 0x02 /* receive threshold bit 1 *//* Register 7: Receive Sensitivity register #2 */#define ACT200L_REG7 0x70#define ACT200L_ENPOS 0x04 /* Ignore the falling edge *//* Register 8,9: Baud Rate Dvider register #1,#2 */#define ACT200L_REG8 0x80#define ACT200L_REG9 0x90#define ACT200L_2400 0x5f#define ACT200L_9600 0x17#define ACT200L_19200 0x0b#define ACT200L_38400 0x05#define ACT200L_57600 0x03#define ACT200L_115200 0x01/* Register 13: Control register #3 */#define ACT200L_REG13 0xd0#define ACT200L_SHDW 0x01 /* Enable access to shadow registers *//* Register 15: Status register */#define ACT200L_REG15 0xf0/* Register 21: Control register #4 */#define ACT200L_REG21 0x50#define ACT200L_EXCK 0x02 /* Disable clock output driver */#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */static void init_act200(void){ int i; __u8 control[] = { ACT200L_REG15, ACT200L_REG13 | ACT200L_SHDW, ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL, ACT200L_REG13, ACT200L_REG7 | ACT200L_ENPOS, ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1, ACT200L_REG5 | ACT200L_RWIDL, ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR, ACT200L_REG3 | ACT200L_B0, ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN, ACT200L_REG8 | (ACT200L_115200 & 0x0f), ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f), ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE }; /* Set DLAB 1. */ soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); /* Set divisor to 12 => 9600 Baud */ soutp(UART_DLM,0); soutp(UART_DLL,12); /* Set DLAB 0. */ soutp(UART_LCR, UART_LCR_WLEN8); /* Set divisor to 12 => 9600 Baud */ /* power supply */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); for (i=0; i<50; i++) { safe_udelay(1000); } /* Reset the dongle : set RTS low for 25 ms */ soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); for (i=0; i<25; i++) { udelay(1000); } soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); udelay(100); /* Clear DTR and set RTS to enter command mode */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); udelay(7);/* send out the control register settings for 115K 7N1 SIR operation */ for (i=0; i<sizeof(control); i++) { soutp(UART_TX, control[i]); /* one byte takes ~1042 usec to transmit at 9600,8N1 */ udelay(1500); } /* back to normal operation */ soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); udelay(50); udelay(1500); soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); /* Set DLAB 1. */ soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); /* Set divisor to 1 => 115200 Baud */ soutp(UART_DLM,0); soutp(UART_DLL,1); /* Set DLAB 0. */ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); /* Set DLAB 0, 7 Bit */ soutp(UART_LCR, UART_LCR_WLEN7); /* enable interrupts */ soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI);}#endifint init_lirc_sir(void){ int retval;#ifdef KERNEL_2_3 init_waitqueue_head(&lirc_read_queue);#endif retval = init_port(); if (retval < 0) return retval; init_hardware(); enable_irq(irq); printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); return 0;}#ifdef MODULE#ifdef KERNEL_2_1#ifdef LIRC_SIR_TEKRAMMODULE_AUTHOR("Christoph Bartelmus");MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210");#elif defined(LIRC_ON_SA1100)MODULE_AUTHOR("Christoph Bartelmus");MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor");#elif defined(LIRC_SIR_ACTISYS_ACT200L)MODULE_AUTHOR("Karl Bongers");MODULE_DESCRIPTION("LIRC driver for Actisys Act200L");#elseMODULE_AUTHOR("Milan Pikula");MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports");#endif#ifdef LIRC_ON_SA1100MODULE_PARM(irq, "i");MODULE_PARM_DESC(irq, "Interrupt (16)");#elseMODULE_PARM(io, "i");MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");MODULE_PARM(irq, "i");MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");#endif#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifEXPORT_NO_SYMBOLS;#endifint init_module(void){ int retval; retval=init_chrdev(); if(retval < 0) return retval; retval = init_lirc_sir(); if (retval) { drop_chrdev(); return retval; } return 0;}void cleanup_module(void){ drop_hardware(); drop_chrdev(); drop_port(); printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -