/* interpret lirc commands */ 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; dprintk("Sending stuff on lirc"); break; case LIRC_GET_LENGTH: return -ENOSYS; break; case LIRC_SET_SEND_DUTY_CYCLE: result = get_user(value, (__u32 *) arg); if (result) return result; if (value <= 0 || value > 100) return -EINVAL; dprintk("SET_SEND_DUTY_CYCLE to %d \n", value); return init_timing_params(value, freq); break; case LIRC_SET_SEND_CARRIER: result = get_user(value, (__u32 *) arg); if (result) return result; if (value > 500000 || value < 20000) return -EINVAL; dprintk("SET_SEND_CARRIER to %d \n",value); return init_timing_params(duty_cycle, value); break; default: return lirc_dev_fop_ioctl(filep, cmd, arg); } return 0; }
// called when the character device is opened static int set_use_inc(void *data) { int result, i; for (i=0 ; i<INPUT_PIN_NUM; i++){ /* initialize timestamp */ do_gettimeofday(&lasttv[i]); result = request_irq(irq_num[i], (irq_handler_t) irq_handler, IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, LIRC_DRIVER_NAME, (void*) 0); switch (result) { case -EBUSY: printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d is busy\n", irq_num[i]); return -EBUSY; case -EINVAL: printk(KERN_ERR LIRC_DRIVER_NAME ": Bad irq number or handler\n"); return -EINVAL; default: dprintk("Interrupt %d obtained\n", irq_num[i]); break; }; /* initialize pulse/space widths */ init_timing_params(duty_cycle, freq); } return 0; }
/* 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(gpio_to_irq(gpio_in_pin), (irq_handler_t) irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING , LIRC_DRIVER_NAME, (void *) 0); switch (result) { case -EBUSY: printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d is busy\n", gpio_to_irq(gpio_in_pin)); return -EBUSY; case -EINVAL: printk(KERN_ERR LIRC_DRIVER_NAME ": Bad irq number or handler, %d\n", gpio_to_irq(gpio_in_pin)); return -EINVAL; default: break; }; /* initialize pulse/space widths */ init_timing_params(duty_cycle, freq); return 0; }
static int serial_ir_tx_carrier(struct rc_dev *dev, u32 carrier) { if (carrier > 500000 || carrier < 20000) return -EINVAL; init_timing_params(serial_ir.duty_cycle, carrier); return 0; }
static int init_port(void) { /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); return 0; }
static ssize_t lirc_rx51_write(struct file *file, const char *buf, size_t n, loff_t *ppos) { int count, i; struct lirc_rx51 *lirc_rx51 = file->private_data; if (n % sizeof(int)) return -EINVAL; count = n / sizeof(int); if ((count > WBUF_LEN) || (count % 2 == 0)) return -EINVAL; /* Wait any pending transfers to finish */ wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0); if (copy_from_user(lirc_rx51->wbuf, buf, n)) return -EFAULT; /* Sanity check the input pulses */ for (i = 0; i < count; i++) if (lirc_rx51->wbuf[i] < 0) return -EINVAL; init_timing_params(lirc_rx51); if (count < WBUF_LEN) lirc_rx51->wbuf[count] = -1; /* Insert termination mark */ /* * Adjust latency requirements so the device doesn't go in too * deep sleep states */ lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50); lirc_rx51_on(lirc_rx51); lirc_rx51->wbuf_index = 1; pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]); /* * Don't return back to the userspace until the transfer has * finished */ wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0); /* We can sleep again */ lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1); return n; }
/* called when the character device is opened timing params initialized and interrupts activated */ static int set_use_inc(void *data) { int result; unsigned long flags; init_timing_params(duty_cycle, freq); /* initialize pulse/space widths */ //initialize timestamp, would not be needed if no RX do_gettimeofday(&lasttv); device_open++; if (gpio_in_pin!=0) { // entered if RX used /* try to set all interrupts to same handler, should work */ result = request_irq(gpiochip->to_irq(gpiochip, RX_OFFSET_GPIOCHIP), (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, RX_OFFSET_GPIOCHIP)); 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, RX_OFFSET_GPIOCHIP)); break; }; 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 for active channel, only */ irqchip->irq_unmask(irqdata); spin_unlock_irqrestore(&lock, flags); } return 0; }
// 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(gci->to_irq(gci, gpio_in_pin), (irq_handler_t) irq_handler, 0, LIRC_DRIVER_NAME, NULL); switch (result) { case -EBUSY: printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d is busy\n", gci->to_irq(gci, 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", gci->to_irq(gci, 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 int serial_ir_tx_duty_cycle(struct rc_dev *dev, u32 cycle) { init_timing_params(cycle, serial_ir.freq); return 0; }
static int 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->input_name = "Serial IR type home-brew"; break; case IR_IRDEO: rcdev->input_name = "Serial IR type IRdeo"; break; case IR_IRDEO_REMOTE: rcdev->input_name = "Serial IR type IRdeo remote"; break; case IR_ANIMAX: rcdev->input_name = "Serial IR type AnimaX"; break; case IR_IGOR: rcdev->input_name = "Serial IR type IgorPlug"; break; } rcdev->input_phys = KBUILD_MODNAME "/input0"; rcdev->input_id.bustype = BUS_HOST; rcdev->input_id.vendor = 0x0001; rcdev->input_id.product = 0x0001; rcdev->input_id.version = 0x0100; rcdev->open = serial_ir_open; rcdev->close = serial_ir_close; rcdev->dev.parent = &serial_ir.pdev->dev; rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER; rcdev->driver_name = KBUILD_MODNAME; rcdev->map_name = RC_MAP_RC6_MCE; rcdev->min_timeout = 1; rcdev->timeout = IR_DEFAULT_TIMEOUT; rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT; rcdev->rx_resolution = 250000; serial_ir.rcdev = rcdev; setup_timer(&serial_ir.timeout_timer, serial_ir_timeout, (unsigned long)&serial_ir); result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler, share_irq ? IRQF_SHARED : 0, KBUILD_MODNAME, &hardware); if (result < 0) { if (result == -EBUSY) dev_err(&dev->dev, "IRQ %d busy\n", irq); else if (result == -EINVAL) dev_err(&dev->dev, "Bad irq number or handler\n"); return result; } /* Reserve io region. */ if ((iommap && (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift, KBUILD_MODNAME) == NULL)) || (!iommap && (devm_request_region(&dev->dev, io, 8, KBUILD_MODNAME) == NULL))) { dev_err(&dev->dev, "port %04x already in use\n", io); dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n"); dev_warn(&dev->dev, "or compile the serial port driver as module and\n"); dev_warn(&dev->dev, "make sure this module is loaded first\n"); return -EBUSY; } result = hardware_init_port(); if (result < 0) return result; /* Initialize pulse/space widths */ init_timing_params(50, 38000); /* 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); return devm_rc_register_device(&dev->dev, rcdev); }
static int init_port(void) { int i, nlow, nhigh; /* Reserve io region. */ #if defined(LIRC_ALLOW_MMAPPED_IO) /* Future MMAP-Developers: Attention! For memory mapped I/O you *might* need to use ioremap() first, for the NSLU2 it's done in boot code. */ if(((iommap != 0) && (request_mem_region(iommap, 8<<ioshift, LIRC_DRIVER_NAME) == NULL)) || ((iommap == 0) && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) #else if(request_region(io, 8, LIRC_DRIVER_NAME)==NULL) #endif { printk(KERN_ERR LIRC_DRIVER_NAME ": port %04x already in use\n", io); printk(KERN_WARNING LIRC_DRIVER_NAME ": use 'setserial /dev/ttySX uart none'\n"); printk(KERN_WARNING LIRC_DRIVER_NAME ": or compile the serial port driver as module and\n"); printk(KERN_WARNING LIRC_DRIVER_NAME ": make sure this module is loaded first\n"); return(-EBUSY); } hardware_init_port(); /* Initialize pulse/space widths */ init_timing_params(duty_cycle, freq); /* If pin is high, then this must be an active low receiver. */ if(sense==-1) { /* wait 1/2 sec for the power supply */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/2); /* 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++; } schedule_timeout(HZ/25); } sense = (nlow >= nhigh ? 1 : 0); printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " "%s receiver\n",sense ? "low":"high"); } else { printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " "%s receiver\n",sense ? "low":"high"); }; return 0; }
static int lirc_ioctl(struct inode *node,struct file *filep,unsigned int cmd, unsigned long arg) { int result; unsigned long value; unsigned int ivalue; switch(cmd) { case LIRC_GET_SEND_MODE: if(!(hardware[type].features&LIRC_CAN_SEND_MASK)) { return(-ENOIOCTLCMD); } result=put_user(LIRC_SEND2MODE (hardware[type].features&LIRC_CAN_SEND_MASK), (unsigned long *) arg); if(result) return(result); break; case LIRC_SET_SEND_MODE: if(!(hardware[type].features&LIRC_CAN_SEND_MASK)) { return(-ENOIOCTLCMD); } result=get_user(value,(unsigned long *) 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"); if(!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) { return(-ENOIOCTLCMD); } result=get_user(ivalue,(unsigned int *) arg); if(result) return(result); if(ivalue<=0 || ivalue>100) return(-EINVAL); return init_timing_params(ivalue, freq); break; case LIRC_SET_SEND_CARRIER: dprintk("SET_SEND_CARRIER\n"); if(!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) { return(-ENOIOCTLCMD); } result=get_user(ivalue,(unsigned int *) arg); if(result) return(result); if(ivalue>500000 || ivalue<20000) return(-EINVAL); return init_timing_params(duty_cycle, ivalue); break; default: return(-ENOIOCTLCMD); } return(0); }
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) #endif { int result; __u32 value; switch (cmd) { case LIRC_GET_SEND_MODE: // if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) // return -ENOIOCTLCMD; // result = put_user(LIRC_SEND2MODE // (hardware[type].features&LIRC_CAN_SEND_MASK), // (__u32 *) arg); if (result) return result; break; case LIRC_SET_SEND_MODE: // if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) // return -ENOIOCTLCMD; 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: // if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) // return -ENOIOCTLCMD; 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: // if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) // return -ENOIOCTLCMD; 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: #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) return lirc_dev_fop_ioctl(node, filep, cmd, arg); #else return lirc_dev_fop_ioctl(filep, cmd, arg); #endif } return 0; }