📄 rte_cb_leds.c
字号:
/* * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support * * Copyright (C) 2002 NEC Corporation * Copyright (C) 2002 Miles Bader <miles@gnu.org> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this * archive for more details. * * Written by Miles Bader <miles@gnu.org> */#include <linux/config.h>#include <linux/init.h>#include <linux/spinlock.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>#define LEDS_MINOR 169 /* Minor device number, using misc major. *//* The actual LED hardware is write-only, so we hold the contents here too. */static unsigned char leds_image[LED_NUM_DIGITS] = { 0 };/* Spinlock protecting the above leds. */static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;/* Common body of LED read/write functions, checks POS and LEN for correctness, declares a variable using IMG_DECL, initialized pointing at the POS position in the LED image buffer, and and iterates COPY_EXPR until BUF is equal to the last buffer position; finally, sets LEN to be the amount actually copied. IMG should be a variable declaration (without an initializer or a terminating semicolon); POS, BUF, and LEN should all be simple variables. */#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr) \do { \ if (pos > LED_NUM_DIGITS) \ len = 0; \ else { \ if (pos + len > LED_NUM_DIGITS) \ len = LED_NUM_DIGITS - pos; \ \ if (len > 0) { \ int _flags; \ const char *_end = buf + len; \ img_decl = &leds_image[pos]; \ \ spin_lock_irqsave (leds_lock, _flags); \ do \ (copy_expr); \ while (buf != _end); \ spin_unlock_irqrestore (mb_sram_lock, _flags); \ } \ } \} while (0)/* Read LEN bytes from LEDs at position POS, into BUF. Returns actual amount read. */unsigned read_leds (unsigned pos, char *buf, unsigned len){ DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++); return len;}/* Write LEN bytes to LEDs at position POS, from BUF. Returns actual amount written. */unsigned write_leds (unsigned pos, const char *buf, unsigned len){ /* We write the actual LED values backwards, because increasing memory addresses reflect LEDs right-to-left. */ volatile char *led = &LED (LED_NUM_DIGITS - pos - 1); /* We invert the value written to the hardware, because 1 = off, and 0 = on. */ DO_LED_COPY (char *img, pos, buf, len, *led-- = 0xFF ^ (*img++ = *buf++)); return len;}/* Device functions. */static ssize_t leds_dev_read (struct file *file, char *buf, size_t len, loff_t *pos){ char temp_buf[LED_NUM_DIGITS]; len = read_leds (*pos, temp_buf, len); if (copy_to_user (buf, temp_buf, len)) return -EFAULT; *pos += len; return len;}static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len, loff_t *pos){ char temp_buf[LED_NUM_DIGITS]; if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS))) return -EFAULT; len = write_leds (*pos, temp_buf, len); *pos += len; return len;}static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence){ if (whence == 1) offs += file->f_pos; /* relative */ else if (whence == 2) offs += LED_NUM_DIGITS; /* end-relative */ if (offs >= 0 && offs <= LED_NUM_DIGITS) file->f_pos = offs; else return -EINVAL;}static struct file_operations leds_fops = { read: leds_dev_read, write: leds_dev_write, llseek: leds_dev_lseek};static struct miscdevice leds_miscdev = { name: "leds", minor: LEDS_MINOR, fops: &leds_fops};int __init leds_dev_init (void){ return misc_register (&leds_miscdev);}__initcall (leds_dev_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -