📄 fusiondev.c
字号:
return -EFAULT; return fusion_property_purchase (dev, id, fusion_id); case _IOC_NR(FUSION_PROPERTY_CEDE): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_property_cede (dev, id, fusion_id); case _IOC_NR(FUSION_PROPERTY_HOLDUP): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_property_holdup (dev, id, fusionee); case _IOC_NR(FUSION_PROPERTY_DESTROY): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_property_destroy (dev, id); } return -ENOSYS;}static intreactor_ioctl (FusionDev *dev, Fusionee *fusionee, unsigned int cmd, unsigned long arg){ int id; int ret; FusionReactorAttach attach; FusionReactorDetach detach; FusionReactorDispatch dispatch; FusionReactorSetCallback callback; FusionID fusion_id = fusionee_id( fusionee ); switch (_IOC_NR(cmd)) { case _IOC_NR(FUSION_REACTOR_NEW): ret = fusion_reactor_new (dev, &id); if (ret) return ret; if (put_user (id, (int*) arg)) { fusion_reactor_destroy (dev, id); return -EFAULT; } return 0; case _IOC_NR(FUSION_REACTOR_ATTACH): if (copy_from_user (&attach, (FusionReactorAttach*) arg, sizeof(attach))) return -EFAULT; return fusion_reactor_attach (dev, attach.reactor_id, attach.channel, fusion_id); case _IOC_NR(FUSION_REACTOR_DETACH): if (copy_from_user (&detach, (FusionReactorDetach*) arg, sizeof(detach))) return -EFAULT; return fusion_reactor_detach (dev, detach.reactor_id, detach.channel, fusion_id); case _IOC_NR(FUSION_REACTOR_DISPATCH): if (copy_from_user (&dispatch, (FusionReactorDispatch*) arg, sizeof(dispatch))) return -EFAULT; if (dispatch.msg_size <= 0) return -EINVAL; /* message data > 64k should be stored in shared memory */ if (dispatch.msg_size > 0x10000) return -EMSGSIZE; return fusion_reactor_dispatch (dev, dispatch.reactor_id, dispatch.channel, dispatch.self ? NULL : fusionee, dispatch.msg_size, dispatch.msg_data); case _IOC_NR(FUSION_REACTOR_DESTROY): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_reactor_destroy (dev, id); case _IOC_NR(FUSION_REACTOR_SET_DISPATCH_CALLBACK): if (copy_from_user (&callback, (FusionReactorSetCallback*) arg, sizeof(callback))) return -EFAULT; return fusion_reactor_set_dispatch_callback (dev, callback.reactor_id, callback.call_id, callback.call_ptr); } return -ENOSYS;}static intshmpool_ioctl (FusionDev *dev, Fusionee *fusionee, unsigned int cmd, unsigned long arg){ int id; int ret; FusionSHMPoolNew pool; FusionSHMPoolAttach attach; FusionSHMPoolDispatch dispatch; FusionID fusion_id = fusionee_id( fusionee ); switch (_IOC_NR(cmd)) { case _IOC_NR(FUSION_SHMPOOL_NEW): if (copy_from_user (&pool, (FusionSHMPoolNew*) arg, sizeof(pool))) return -EFAULT; ret = fusion_shmpool_new (dev, &pool); if (ret) return ret; if (copy_to_user ((FusionSHMPoolNew*) arg, &pool, sizeof(pool))) { fusion_shmpool_destroy (dev, pool.pool_id); return -EFAULT; } return 0; case _IOC_NR(FUSION_SHMPOOL_ATTACH): if (copy_from_user (&attach, (FusionSHMPoolAttach*) arg, sizeof(attach))) return -EFAULT; ret = fusion_shmpool_attach (dev, &attach, fusion_id); if (ret) return ret; if (copy_to_user ((FusionSHMPoolAttach*) arg, &attach, sizeof(attach))) { fusion_shmpool_detach (dev, attach.pool_id, fusion_id); return -EFAULT; } return 0; case _IOC_NR(FUSION_SHMPOOL_DETACH): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_shmpool_detach (dev, id, fusion_id); case _IOC_NR(FUSION_SHMPOOL_DISPATCH): if (copy_from_user (&dispatch, (FusionSHMPoolDispatch*) arg, sizeof(dispatch))) return -EFAULT; return fusion_shmpool_dispatch (dev, &dispatch, fusionee); case _IOC_NR(FUSION_SHMPOOL_DESTROY): if (get_user (id, (int*) arg)) return -EFAULT; return fusion_shmpool_destroy (dev, id); } return -ENOSYS;}static intfusion_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ Fusionee *fusionee = file->private_data; FusionDev *dev = fusion_devs[iminor(inode)]; DEBUG( "fusion_ioctl (0x%08x)\n", cmd ); switch (_IOC_TYPE(cmd)) { case FT_LOUNGE: return lounge_ioctl( file, dev, fusionee, cmd, arg ); case FT_MESSAGING: return messaging_ioctl( dev, fusionee, cmd, arg ); case FT_CALL: return call_ioctl( dev, fusionee, cmd, arg ); case FT_REF: return ref_ioctl( dev, fusionee, cmd, arg ); case FT_SKIRMISH: return skirmish_ioctl( dev, fusionee, cmd, arg ); case FT_PROPERTY: return property_ioctl( dev, fusionee, cmd, arg ); case FT_REACTOR: return reactor_ioctl( dev, fusionee, cmd, arg ); case FT_SHMPOOL: return shmpool_ioctl( dev, fusionee, cmd, arg ); } return -ENOSYS;}static intfusion_mmap( struct file *file, struct vm_area_struct *vma ){ Fusionee *fusionee = file->private_data; FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)]; unsigned int size; if (vma->vm_pgoff != 0) return -EINVAL; size = vma->vm_end - vma->vm_start; if (!size || size > PAGE_SIZE) return -EINVAL; if (!dev->shared_area) { if (fusionee_id( fusionee ) != FUSION_ID_MASTER) return -EPERM; dev->shared_area = get_zeroed_page( GFP_KERNEL ); if (!dev->shared_area) return -ENOMEM; SetPageReserved( virt_to_page(dev->shared_area) ); }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) return remap_pfn_range( vma, vma->vm_start, virt_to_phys((void*)dev->shared_area) >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot );#else return io_remap_page_range( vma->vm_start, virt_to_phys((void*)dev->shared_area), PAGE_SIZE, vma->vm_page_prot );#endif}static struct file_operations fusion_fops = { .owner = THIS_MODULE, .open = fusion_open, .flush = fusion_flush, .release = fusion_release, .read = fusion_read, .poll = fusion_poll, .ioctl = fusion_ioctl, .mmap = fusion_mmap};/******************************************************************************/#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)static int __initregister_devices(void){ int i; if (register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) { printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR); return -EIO; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) fusion_class = class_create (THIS_MODULE, "fusion");#else fusion_class = class_simple_create (THIS_MODULE, "fusion");#endif if (IS_ERR(fusion_class)) { unregister_chrdev (FUSION_MAJOR, "fusion"); return PTR_ERR(fusion_class); }#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) devfs_mk_dir("fusion");#endif for (i=0; i<NUM_MINORS; i++) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15) class_device_create (fusion_class, NULL, MKDEV(FUSION_MAJOR, i), NULL, "fusion%d", i);#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) class_device_create (fusion_class, MKDEV(FUSION_MAJOR, i), NULL, "fusion%d", i);#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2) class_simple_device_add (fusion_class, MKDEV(FUSION_MAJOR, i), NULL, "fusion%d", i);#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) devfs_mk_cdev (MKDEV(FUSION_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, "fusion/%d", i);#endif } return 0;}#elsestatic int __initregister_devices(void){ int i; char buf[16]; if (devfs_register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) { printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR); return -EIO; } for (i=0; i<NUM_MINORS; i++) { snprintf (buf, 16, "fusion/%d", i); devfs_handles[i] = devfs_register (NULL, buf, DEVFS_FL_DEFAULT, FUSION_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, &fusion_fops, NULL); } return 0;}#endifint __initfusion_init(void){ int ret; ret = register_devices(); if (ret) return ret; proc_fusion_dir = proc_mkdir ("fusion", NULL); return 0;}/******************************************************************************/#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)static void __exitderegister_devices(void){ int i; unregister_chrdev (FUSION_MAJOR, "fusion"); for (i=0; i<NUM_MINORS; i++) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) class_device_destroy (fusion_class, MKDEV(FUSION_MAJOR, i));#else class_simple_device_remove (MKDEV(FUSION_MAJOR, i));#endif#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) devfs_remove ("fusion/%d", i);#endif }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) class_destroy (fusion_class);#else class_simple_destroy (fusion_class);#endif#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) devfs_remove ("fusion");#endif}#elsestatic void __exitderegister_devices(void){ int i; devfs_unregister_chrdev (FUSION_MAJOR, "fusion"); for (i=0; i<NUM_MINORS; i++) devfs_unregister (devfs_handles[i]);}#endifvoid __exitfusion_exit(void){ deregister_devices(); remove_proc_entry ("fusion", NULL);}module_init(fusion_init);module_exit(fusion_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -