|
@@ -3,7 +3,6 @@
|
|
|
*/
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
-#include <linux/smp_lock.h>
|
|
|
#include <linux/errno.h>
|
|
|
#include <linux/kernel.h>
|
|
|
#include <linux/miscdevice.h>
|
|
@@ -26,6 +25,7 @@
|
|
|
static unsigned long anslcd_short_delay = 80;
|
|
|
static unsigned long anslcd_long_delay = 3280;
|
|
|
static volatile unsigned char __iomem *anslcd_ptr;
|
|
|
+static DEFINE_MUTEX(anslcd_mutex);
|
|
|
|
|
|
#undef DEBUG
|
|
|
|
|
@@ -65,26 +65,31 @@ anslcd_write( struct file * file, const char __user * buf,
|
|
|
|
|
|
if (!access_ok(VERIFY_READ, buf, count))
|
|
|
return -EFAULT;
|
|
|
+
|
|
|
+ mutex_lock(&anslcd_mutex);
|
|
|
for ( i = *ppos; count > 0; ++i, ++p, --count )
|
|
|
{
|
|
|
char c;
|
|
|
__get_user(c, p);
|
|
|
anslcd_write_byte_data( c );
|
|
|
}
|
|
|
+ mutex_unlock(&anslcd_mutex);
|
|
|
*ppos = i;
|
|
|
return p - buf;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-anslcd_ioctl( struct inode * inode, struct file * file,
|
|
|
- unsigned int cmd, unsigned long arg )
|
|
|
+static long
|
|
|
+anslcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
|
{
|
|
|
char ch, __user *temp;
|
|
|
+ long ret = 0;
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
printk(KERN_DEBUG "LCD: ioctl(%d,%d)\n",cmd,arg);
|
|
|
#endif
|
|
|
|
|
|
+ mutex_lock(&anslcd_mutex);
|
|
|
+
|
|
|
switch ( cmd )
|
|
|
{
|
|
|
case ANSLCD_CLEAR:
|
|
@@ -93,7 +98,7 @@ anslcd_ioctl( struct inode * inode, struct file * file,
|
|
|
anslcd_write_byte_ctrl ( 0x06 );
|
|
|
anslcd_write_byte_ctrl ( 0x01 );
|
|
|
anslcd_write_byte_ctrl ( 0x02 );
|
|
|
- return 0;
|
|
|
+ break;
|
|
|
case ANSLCD_SENDCTRL:
|
|
|
temp = (char __user *) arg;
|
|
|
__get_user(ch, temp);
|
|
@@ -101,33 +106,37 @@ anslcd_ioctl( struct inode * inode, struct file * file,
|
|
|
anslcd_write_byte_ctrl ( ch );
|
|
|
__get_user(ch, temp);
|
|
|
}
|
|
|
- return 0;
|
|
|
+ break;
|
|
|
case ANSLCD_SETSHORTDELAY:
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
- return -EACCES;
|
|
|
- anslcd_short_delay=arg;
|
|
|
- return 0;
|
|
|
+ ret =-EACCES;
|
|
|
+ else
|
|
|
+ anslcd_short_delay=arg;
|
|
|
+ break;
|
|
|
case ANSLCD_SETLONGDELAY:
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
|
- return -EACCES;
|
|
|
- anslcd_long_delay=arg;
|
|
|
- return 0;
|
|
|
+ ret = -EACCES;
|
|
|
+ else
|
|
|
+ anslcd_long_delay=arg;
|
|
|
+ break;
|
|
|
default:
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
}
|
|
|
+
|
|
|
+ mutex_unlock(&anslcd_mutex);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
anslcd_open( struct inode * inode, struct file * file )
|
|
|
{
|
|
|
- cycle_kernel_lock();
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
const struct file_operations anslcd_fops = {
|
|
|
- .write = anslcd_write,
|
|
|
- .ioctl = anslcd_ioctl,
|
|
|
- .open = anslcd_open,
|
|
|
+ .write = anslcd_write,
|
|
|
+ .unlocked_ioctl = anslcd_ioctl,
|
|
|
+ .open = anslcd_open,
|
|
|
};
|
|
|
|
|
|
static struct miscdevice anslcd_dev = {
|
|
@@ -168,6 +177,7 @@ anslcd_init(void)
|
|
|
printk(KERN_DEBUG "LCD: init\n");
|
|
|
#endif
|
|
|
|
|
|
+ mutex_lock(&anslcd_mutex);
|
|
|
anslcd_write_byte_ctrl ( 0x38 );
|
|
|
anslcd_write_byte_ctrl ( 0x0c );
|
|
|
anslcd_write_byte_ctrl ( 0x06 );
|
|
@@ -176,6 +186,7 @@ anslcd_init(void)
|
|
|
for(a=0;a<80;a++) {
|
|
|
anslcd_write_byte_data(anslcd_logo[a]);
|
|
|
}
|
|
|
+ mutex_unlock(&anslcd_mutex);
|
|
|
return 0;
|
|
|
}
|
|
|
|