📄 ibmasmfs.c
字号:
return count;}static int event_file_open(struct inode *inode, struct file *file){ struct ibmasmfs_event_data *event_data; struct service_processor *sp; if (!inode->u.generic_ip) return -ENODEV; sp = inode->u.generic_ip; event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL); if (!event_data) return -ENOMEM; ibmasm_event_reader_register(sp, &event_data->reader); event_data->sp = sp; file->private_data = event_data; return 0;}static int event_file_close(struct inode *inode, struct file *file){ struct ibmasmfs_event_data *event_data = file->private_data; ibmasm_event_reader_unregister(event_data->sp, &event_data->reader); kfree(event_data); return 0;}static ssize_t event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset){ struct ibmasmfs_event_data *event_data = file->private_data; struct event_reader *reader = &event_data->reader; int ret; if (*offset < 0) return -EINVAL; if (count == 0 || count > IBMASM_EVENT_MAX_SIZE) return 0; if (*offset != 0) return 0; ret = ibmasm_get_next_event(event_data->sp, reader); if (ret <= 0) return ret; if (count < reader->data_size) return -EINVAL; if (copy_to_user(buf, reader->data, reader->data_size)) return -EFAULT; return reader->data_size;}static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset){ struct ibmasmfs_event_data *event_data = file->private_data; if (*offset < 0) return -EINVAL; if (count != 1) return 0; if (*offset != 0) return 0; wake_up_interruptible(&event_data->reader.wait); return 0;}static int r_heartbeat_file_open(struct inode *inode, struct file *file){ struct ibmasmfs_heartbeat_data *rhbeat; if (!inode->u.generic_ip) return -ENODEV; rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL); if (!rhbeat) return -ENOMEM; rhbeat->sp = (struct service_processor *)inode->u.generic_ip; rhbeat->active = 0; ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); file->private_data = rhbeat; return 0;}static int r_heartbeat_file_close(struct inode *inode, struct file *file){ struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; kfree(rhbeat); return 0;}static ssize_t r_heartbeat_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset){ struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; unsigned long flags; int result; if (*offset < 0) return -EINVAL; if (count == 0 || count > 1024) return 0; if (*offset != 0) return 0; /* allow only one reverse heartbeat per process */ spin_lock_irqsave(&rhbeat->sp->lock, flags); if (rhbeat->active) { spin_unlock_irqrestore(&rhbeat->sp->lock, flags); return -EBUSY; } rhbeat->active = 1; spin_unlock_irqrestore(&rhbeat->sp->lock, flags); result = ibmasm_start_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); rhbeat->active = 0; return result;}static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset){ struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; if (*offset < 0) return -EINVAL; if (count != 1) return 0; if (*offset != 0) return 0; if (rhbeat->active) ibmasm_stop_reverse_heartbeat(&rhbeat->heartbeat); return 1;}static int remote_settings_file_open(struct inode *inode, struct file *file){ file->private_data = inode->u.generic_ip; return 0;}static int remote_settings_file_close(struct inode *inode, struct file *file){ return 0;}static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset){ void __iomem *address = (void __iomem *)file->private_data; unsigned char *page; int retval; int len = 0; unsigned int value; if (*offset < 0) return -EINVAL; if (count == 0 || count > 1024) return 0; if (*offset != 0) return 0; page = (unsigned char *)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; value = readl(address); len = sprintf(page, "%d\n", value); if (copy_to_user(buf, page, len)) { retval = -EFAULT; goto exit; } *offset += len; retval = len;exit: free_page((unsigned long)page); return retval;}static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset){ void __iomem *address = (void __iomem *)file->private_data; char *buff; unsigned int value; if (*offset < 0) return -EINVAL; if (count == 0 || count > 1024) return 0; if (*offset != 0) return 0; buff = kmalloc (count + 1, GFP_KERNEL); if (!buff) return -ENOMEM; memset(buff, 0x0, count + 1); if (copy_from_user(buff, ubuff, count)) { kfree(buff); return -EFAULT; } value = simple_strtoul(buff, NULL, 10); writel(value, address); kfree(buff); return count;}static int remote_event_file_open(struct inode *inode, struct file *file){ struct service_processor *sp; unsigned long flags; struct remote_queue *q; file->private_data = inode->u.generic_ip; sp = file->private_data; q = &sp->remote_queue; /* allow only one event reader */ spin_lock_irqsave(&sp->lock, flags); if (q->open) { spin_unlock_irqrestore(&sp->lock, flags); return -EBUSY; } q->open = 1; spin_unlock_irqrestore(&sp->lock, flags); enable_mouse_interrupts(sp); return 0;}static int remote_event_file_close(struct inode *inode, struct file *file){ struct service_processor *sp = file->private_data; disable_mouse_interrupts(sp); wake_up_interruptible(&sp->remote_queue.wait); sp->remote_queue.open = 0; return 0;}static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset){ struct service_processor *sp = file->private_data; struct remote_queue *q = &sp->remote_queue; size_t data_size; struct remote_event *reader = q->reader; size_t num_events; if (*offset < 0) return -EINVAL; if (count == 0 || count > 1024) return 0; if (*offset != 0) return 0; if (wait_event_interruptible(q->wait, q->reader != q->writer)) return -ERESTARTSYS; /* only get multiples of struct remote_event */ num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q)); if (!num_events) return 0; data_size = num_events * sizeof(struct remote_event); if (copy_to_user(buf, reader, data_size)) return -EFAULT; ibmasm_advance_reader(q, num_events); return data_size;}static struct file_operations command_fops = { .open = command_file_open, .release = command_file_close, .read = command_file_read, .write = command_file_write,};static struct file_operations event_fops = { .open = event_file_open, .release = event_file_close, .read = event_file_read, .write = event_file_write,};static struct file_operations r_heartbeat_fops = { .open = r_heartbeat_file_open, .release = r_heartbeat_file_close, .read = r_heartbeat_file_read, .write = r_heartbeat_file_write,};static struct file_operations remote_settings_fops = { .open = remote_settings_file_open, .release = remote_settings_file_close, .read = remote_settings_file_read, .write = remote_settings_file_write,};static struct file_operations remote_event_fops = { .open = remote_event_file_open, .release = remote_event_file_close, .read = remote_event_file_read,};static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root){ struct list_head *entry; struct service_processor *sp; list_for_each(entry, &service_processors) { struct dentry *dir; struct dentry *remote_dir; sp = list_entry(entry, struct service_processor, node); dir = ibmasmfs_create_dir(sb, root, sp->dirname); if (!dir) continue; ibmasmfs_create_file(sb, dir, "command", &command_fops, sp, S_IRUSR|S_IWUSR); ibmasmfs_create_file(sb, dir, "event", &event_fops, sp, S_IRUSR|S_IWUSR); ibmasmfs_create_file(sb, dir, "reverse_heartbeat", &r_heartbeat_fops, sp, S_IRUSR|S_IWUSR); remote_dir = ibmasmfs_create_dir(sb, dir, "remote_video"); if (!remote_dir) continue; ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR); ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -