1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * file.c - part of debugfs, a tiny little debug file system 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 2004 Greg Kroah-Hartman <[email protected]> 5*1da177e4SLinus Torvalds * Copyright (C) 2004 IBM Inc. 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 8*1da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License version 9*1da177e4SLinus Torvalds * 2 as published by the Free Software Foundation. 10*1da177e4SLinus Torvalds * 11*1da177e4SLinus Torvalds * debugfs is for people to use instead of /proc or /sys. 12*1da177e4SLinus Torvalds * See Documentation/DocBook/kernel-api for more details. 13*1da177e4SLinus Torvalds * 14*1da177e4SLinus Torvalds */ 15*1da177e4SLinus Torvalds 16*1da177e4SLinus Torvalds #include <linux/config.h> 17*1da177e4SLinus Torvalds #include <linux/module.h> 18*1da177e4SLinus Torvalds #include <linux/fs.h> 19*1da177e4SLinus Torvalds #include <linux/pagemap.h> 20*1da177e4SLinus Torvalds #include <linux/debugfs.h> 21*1da177e4SLinus Torvalds 22*1da177e4SLinus Torvalds static ssize_t default_read_file(struct file *file, char __user *buf, 23*1da177e4SLinus Torvalds size_t count, loff_t *ppos) 24*1da177e4SLinus Torvalds { 25*1da177e4SLinus Torvalds return 0; 26*1da177e4SLinus Torvalds } 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds static ssize_t default_write_file(struct file *file, const char __user *buf, 29*1da177e4SLinus Torvalds size_t count, loff_t *ppos) 30*1da177e4SLinus Torvalds { 31*1da177e4SLinus Torvalds return count; 32*1da177e4SLinus Torvalds } 33*1da177e4SLinus Torvalds 34*1da177e4SLinus Torvalds static int default_open(struct inode *inode, struct file *file) 35*1da177e4SLinus Torvalds { 36*1da177e4SLinus Torvalds if (inode->u.generic_ip) 37*1da177e4SLinus Torvalds file->private_data = inode->u.generic_ip; 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds return 0; 40*1da177e4SLinus Torvalds } 41*1da177e4SLinus Torvalds 42*1da177e4SLinus Torvalds struct file_operations debugfs_file_operations = { 43*1da177e4SLinus Torvalds .read = default_read_file, 44*1da177e4SLinus Torvalds .write = default_write_file, 45*1da177e4SLinus Torvalds .open = default_open, 46*1da177e4SLinus Torvalds }; 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds #define simple_type(type, format, temptype, strtolfn) \ 49*1da177e4SLinus Torvalds static ssize_t read_file_##type(struct file *file, char __user *user_buf, \ 50*1da177e4SLinus Torvalds size_t count, loff_t *ppos) \ 51*1da177e4SLinus Torvalds { \ 52*1da177e4SLinus Torvalds char buf[32]; \ 53*1da177e4SLinus Torvalds type *val = file->private_data; \ 54*1da177e4SLinus Torvalds \ 55*1da177e4SLinus Torvalds snprintf(buf, sizeof(buf), format "\n", *val); \ 56*1da177e4SLinus Torvalds return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ 57*1da177e4SLinus Torvalds } \ 58*1da177e4SLinus Torvalds static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\ 59*1da177e4SLinus Torvalds size_t count, loff_t *ppos) \ 60*1da177e4SLinus Torvalds { \ 61*1da177e4SLinus Torvalds char *endp; \ 62*1da177e4SLinus Torvalds char buf[32]; \ 63*1da177e4SLinus Torvalds int buf_size; \ 64*1da177e4SLinus Torvalds type *val = file->private_data; \ 65*1da177e4SLinus Torvalds temptype tmp; \ 66*1da177e4SLinus Torvalds \ 67*1da177e4SLinus Torvalds memset(buf, 0x00, sizeof(buf)); \ 68*1da177e4SLinus Torvalds buf_size = min(count, (sizeof(buf)-1)); \ 69*1da177e4SLinus Torvalds if (copy_from_user(buf, user_buf, buf_size)) \ 70*1da177e4SLinus Torvalds return -EFAULT; \ 71*1da177e4SLinus Torvalds \ 72*1da177e4SLinus Torvalds tmp = strtolfn(buf, &endp, 0); \ 73*1da177e4SLinus Torvalds if ((endp == buf) || ((type)tmp != tmp)) \ 74*1da177e4SLinus Torvalds return -EINVAL; \ 75*1da177e4SLinus Torvalds *val = tmp; \ 76*1da177e4SLinus Torvalds return count; \ 77*1da177e4SLinus Torvalds } \ 78*1da177e4SLinus Torvalds static struct file_operations fops_##type = { \ 79*1da177e4SLinus Torvalds .read = read_file_##type, \ 80*1da177e4SLinus Torvalds .write = write_file_##type, \ 81*1da177e4SLinus Torvalds .open = default_open, \ 82*1da177e4SLinus Torvalds }; 83*1da177e4SLinus Torvalds simple_type(u8, "%c", unsigned long, simple_strtoul); 84*1da177e4SLinus Torvalds simple_type(u16, "%hi", unsigned long, simple_strtoul); 85*1da177e4SLinus Torvalds simple_type(u32, "%i", unsigned long, simple_strtoul); 86*1da177e4SLinus Torvalds 87*1da177e4SLinus Torvalds /** 88*1da177e4SLinus Torvalds * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 89*1da177e4SLinus Torvalds * 90*1da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 91*1da177e4SLinus Torvalds * @mode: the permission that the file should have 92*1da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 93*1da177e4SLinus Torvalds * directory dentry if set. If this paramater is NULL, then the 94*1da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 95*1da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 96*1da177e4SLinus Torvalds * from. 97*1da177e4SLinus Torvalds * 98*1da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 99*1da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 100*1da177e4SLinus Torvalds * set, it can be read from, and written to. 101*1da177e4SLinus Torvalds * 102*1da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 103*1da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 104*1da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 105*1da177e4SLinus Torvalds * you are responsible here.) If an error occurs, NULL will be returned. 106*1da177e4SLinus Torvalds * 107*1da177e4SLinus Torvalds * If debugfs is not enabled in the kernel, the value -ENODEV will be 108*1da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 109*1da177e4SLinus Torvalds * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 110*1da177e4SLinus Torvalds * code. 111*1da177e4SLinus Torvalds */ 112*1da177e4SLinus Torvalds struct dentry *debugfs_create_u8(const char *name, mode_t mode, 113*1da177e4SLinus Torvalds struct dentry *parent, u8 *value) 114*1da177e4SLinus Torvalds { 115*1da177e4SLinus Torvalds return debugfs_create_file(name, mode, parent, value, &fops_u8); 116*1da177e4SLinus Torvalds } 117*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u8); 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds /** 120*1da177e4SLinus Torvalds * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 121*1da177e4SLinus Torvalds * 122*1da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 123*1da177e4SLinus Torvalds * @mode: the permission that the file should have 124*1da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 125*1da177e4SLinus Torvalds * directory dentry if set. If this paramater is NULL, then the 126*1da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 127*1da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 128*1da177e4SLinus Torvalds * from. 129*1da177e4SLinus Torvalds * 130*1da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 131*1da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 132*1da177e4SLinus Torvalds * set, it can be read from, and written to. 133*1da177e4SLinus Torvalds * 134*1da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 135*1da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 136*1da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 137*1da177e4SLinus Torvalds * you are responsible here.) If an error occurs, NULL will be returned. 138*1da177e4SLinus Torvalds * 139*1da177e4SLinus Torvalds * If debugfs is not enabled in the kernel, the value -ENODEV will be 140*1da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 141*1da177e4SLinus Torvalds * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 142*1da177e4SLinus Torvalds * code. 143*1da177e4SLinus Torvalds */ 144*1da177e4SLinus Torvalds struct dentry *debugfs_create_u16(const char *name, mode_t mode, 145*1da177e4SLinus Torvalds struct dentry *parent, u16 *value) 146*1da177e4SLinus Torvalds { 147*1da177e4SLinus Torvalds return debugfs_create_file(name, mode, parent, value, &fops_u16); 148*1da177e4SLinus Torvalds } 149*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u16); 150*1da177e4SLinus Torvalds 151*1da177e4SLinus Torvalds /** 152*1da177e4SLinus Torvalds * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. 153*1da177e4SLinus Torvalds * 154*1da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 155*1da177e4SLinus Torvalds * @mode: the permission that the file should have 156*1da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 157*1da177e4SLinus Torvalds * directory dentry if set. If this paramater is NULL, then the 158*1da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 159*1da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 160*1da177e4SLinus Torvalds * from. 161*1da177e4SLinus Torvalds * 162*1da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 163*1da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 164*1da177e4SLinus Torvalds * set, it can be read from, and written to. 165*1da177e4SLinus Torvalds * 166*1da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 167*1da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 168*1da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 169*1da177e4SLinus Torvalds * you are responsible here.) If an error occurs, NULL will be returned. 170*1da177e4SLinus Torvalds * 171*1da177e4SLinus Torvalds * If debugfs is not enabled in the kernel, the value -ENODEV will be 172*1da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 173*1da177e4SLinus Torvalds * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 174*1da177e4SLinus Torvalds * code. 175*1da177e4SLinus Torvalds */ 176*1da177e4SLinus Torvalds struct dentry *debugfs_create_u32(const char *name, mode_t mode, 177*1da177e4SLinus Torvalds struct dentry *parent, u32 *value) 178*1da177e4SLinus Torvalds { 179*1da177e4SLinus Torvalds return debugfs_create_file(name, mode, parent, value, &fops_u32); 180*1da177e4SLinus Torvalds } 181*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_u32); 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds static ssize_t read_file_bool(struct file *file, char __user *user_buf, 184*1da177e4SLinus Torvalds size_t count, loff_t *ppos) 185*1da177e4SLinus Torvalds { 186*1da177e4SLinus Torvalds char buf[3]; 187*1da177e4SLinus Torvalds u32 *val = file->private_data; 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds if (*val) 190*1da177e4SLinus Torvalds buf[0] = 'Y'; 191*1da177e4SLinus Torvalds else 192*1da177e4SLinus Torvalds buf[0] = 'N'; 193*1da177e4SLinus Torvalds buf[1] = '\n'; 194*1da177e4SLinus Torvalds buf[2] = 0x00; 195*1da177e4SLinus Torvalds return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 196*1da177e4SLinus Torvalds } 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds static ssize_t write_file_bool(struct file *file, const char __user *user_buf, 199*1da177e4SLinus Torvalds size_t count, loff_t *ppos) 200*1da177e4SLinus Torvalds { 201*1da177e4SLinus Torvalds char buf[32]; 202*1da177e4SLinus Torvalds int buf_size; 203*1da177e4SLinus Torvalds u32 *val = file->private_data; 204*1da177e4SLinus Torvalds 205*1da177e4SLinus Torvalds buf_size = min(count, (sizeof(buf)-1)); 206*1da177e4SLinus Torvalds if (copy_from_user(buf, user_buf, buf_size)) 207*1da177e4SLinus Torvalds return -EFAULT; 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds switch (buf[0]) { 210*1da177e4SLinus Torvalds case 'y': 211*1da177e4SLinus Torvalds case 'Y': 212*1da177e4SLinus Torvalds case '1': 213*1da177e4SLinus Torvalds *val = 1; 214*1da177e4SLinus Torvalds break; 215*1da177e4SLinus Torvalds case 'n': 216*1da177e4SLinus Torvalds case 'N': 217*1da177e4SLinus Torvalds case '0': 218*1da177e4SLinus Torvalds *val = 0; 219*1da177e4SLinus Torvalds break; 220*1da177e4SLinus Torvalds } 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds return count; 223*1da177e4SLinus Torvalds } 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds static struct file_operations fops_bool = { 226*1da177e4SLinus Torvalds .read = read_file_bool, 227*1da177e4SLinus Torvalds .write = write_file_bool, 228*1da177e4SLinus Torvalds .open = default_open, 229*1da177e4SLinus Torvalds }; 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds /** 232*1da177e4SLinus Torvalds * debugfs_create_bool - create a file in the debugfs filesystem that is used to read and write a boolean value. 233*1da177e4SLinus Torvalds * 234*1da177e4SLinus Torvalds * @name: a pointer to a string containing the name of the file to create. 235*1da177e4SLinus Torvalds * @mode: the permission that the file should have 236*1da177e4SLinus Torvalds * @parent: a pointer to the parent dentry for this file. This should be a 237*1da177e4SLinus Torvalds * directory dentry if set. If this paramater is NULL, then the 238*1da177e4SLinus Torvalds * file will be created in the root of the debugfs filesystem. 239*1da177e4SLinus Torvalds * @value: a pointer to the variable that the file should read to and write 240*1da177e4SLinus Torvalds * from. 241*1da177e4SLinus Torvalds * 242*1da177e4SLinus Torvalds * This function creates a file in debugfs with the given name that 243*1da177e4SLinus Torvalds * contains the value of the variable @value. If the @mode variable is so 244*1da177e4SLinus Torvalds * set, it can be read from, and written to. 245*1da177e4SLinus Torvalds * 246*1da177e4SLinus Torvalds * This function will return a pointer to a dentry if it succeeds. This 247*1da177e4SLinus Torvalds * pointer must be passed to the debugfs_remove() function when the file is 248*1da177e4SLinus Torvalds * to be removed (no automatic cleanup happens if your module is unloaded, 249*1da177e4SLinus Torvalds * you are responsible here.) If an error occurs, NULL will be returned. 250*1da177e4SLinus Torvalds * 251*1da177e4SLinus Torvalds * If debugfs is not enabled in the kernel, the value -ENODEV will be 252*1da177e4SLinus Torvalds * returned. It is not wise to check for this value, but rather, check for 253*1da177e4SLinus Torvalds * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 254*1da177e4SLinus Torvalds * code. 255*1da177e4SLinus Torvalds */ 256*1da177e4SLinus Torvalds struct dentry *debugfs_create_bool(const char *name, mode_t mode, 257*1da177e4SLinus Torvalds struct dentry *parent, u32 *value) 258*1da177e4SLinus Torvalds { 259*1da177e4SLinus Torvalds return debugfs_create_file(name, mode, parent, value, &fops_bool); 260*1da177e4SLinus Torvalds } 261*1da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(debugfs_create_bool); 262*1da177e4SLinus Torvalds 263