/* Actually put the data into the buffer */

 while (length && *Message_Ptr) {

  /* Because the buffer is in the user data segment,

  * not the kernel data segment, assignment wouldn't

  * work. Instead, we have to use put_user which

  * copies data from the kernel data segment to the

  * user data segment. */

  put_user(*(Message_Ptr++), buffer++);

  length--;

  bytes_read++;

 }

#ifdef DEBUG

 printk("Read %d bytes, %d left\n", bytes_read, length);

#endif

 /* Read functions are supposed to return the number

 * of bytes actually inserted into the buffer */

 return bytes_read;

}

/* This function is called when somebody tries to write into our device file. */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

static ssize_t device_write(struct file *file, const char *buffer, size_t length, loff_t *offset)

#else

static int device_write(struct inode *inode, struct file *file, const char *buffer, int length)

#endif

{

 int i;

#ifdef DEBUG

 printk("device_write(%p,%s,%d)", file, buffer, length);

#endif

 for(i=0; i

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

  get_user(Message[i], buffer+i);

#else

  Message[i] = get_user(buffer+i);

#endif

 Message_Ptr = Message;

 /* Again, return the number of input characters used */

 return i;

}

/* This function is called whenever a process tries to

* do an ioctl on our device file. We get two extra

* parameters (additional to the inode and file

* structures, which all device functions get): the number

* of the ioctl called and the parameter given to the ioctl function.

*

* If the ioctl is write or read/write (meaning output

* is returned to the calling process), the ioctl call

* returns the output of this function. */

int device_ioctl(struct inode *inode, struct file *file,

 unsigned int ioctl_num, /* The number of the ioctl */

 unsigned long ioctl_param) /* The parameter to it */

{

 int i;

 char *temp;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

 char ch;

#endif

 /* Switch according to the ioctl called */

 switch (ioctl_num) {

 case IOCTL_SET_MSG:

  /* Receive a pointer to a message (in user space)

  * and set that to be the device's message. */

  /* Get the parameter given to ioctl by the process */

  temp = (char*)ioctl_param;

  /* Find the length of the message */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

  get_user(ch, temp);

  for (i=0; ch && i

#else

  for (i=0; get_user(temp) && i

#endif

  /* Don't reinvent the wheel - call device_write */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

  device_write(file, (char*)ioctl_param, i, 0);

#else

  device_write(inode, file, (char*)ioctl_param, i);

#endif

  break;

 case IOCTL_GET_MSG:

Перейти на страницу:

Все книги серии Проект russian ldp

Похожие книги