typedef struct Skel_Clientdata {
Skel_Hw *board;
int flags;
/* .... */
} Skel_Clientdata;
struct file_operations skel_fops;
struct file_operations skel_raw_fops;
int skel_open (struct inode *inode, struct file *filp)
{
Skel_Hw *board;
Skel_Clientdata *data;
int err;
if (SKEL_BOARD(inode->i_rdev) >= skel_boards) return -ENODEV;
board = skel_hw + BOARDNO(inode->i_rdev);
switch (SKEL_MODE(inode->i_rdev)) /* node selection */
{
case 0: break; /* normal mode */
case 1: filp->f_op = skel_raw_fops; break; /* raw mode */
default: return -ENODEV;
}
data = kmalloc(sizeof(Skel_Clientdata), GFP_KERNEL);
if (!data) return -ENOMEM;
filp->private_data = data;
data->board = board;
data->flags = SKEL_DEFAULT_FLAGS;
fill_any_further_field
if (board->usecount == 0) { /* first open */
if (board->hwirq >= 0) {
if ( (err=request_irq(board->hwirq,skel_interrupt,0,"skel")) !=
0) {
kfree(data);
return err; /* or go on, at your will */
}
board->irq=board->hwirq;
}
skel_initialize_the_board();
}
board->usecount++;
MOD_INC_USE_COUNT;
return 0;
}
void skel_close (struct inode *inode, struct file *filp)
{
Skel_Clientdata *data=filp->private_data;
Skel_Board *board=data->board;
if (board->usecount == 1) { /* last close */
if (board->irq) {
free_irq(board->irq);
board->irq = -1;
}
skel_shutdown_board
}
kfree(data);
filp->private_data=NULL;
board->usecount--;
MOD_DEC_USE_COUNT;
return;
}
Copyright © 1994 - 2019 Linux Journal. All rights reserved.