⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lad_pad.c

📁 Linux嵌入式设计配套光盘,学习嵌入式设计可参考
💻 C
📖 第 1 页 / 共 2 页
字号:
      if(pfile->f_mode & FMODE_READ){        up(&ladpad_read_sem);      }      return -EBUSY;    }  }  /* Log open call */  if (debuglvl >= 3) {    printk(KERN_INFO "ladpad opened\n");  }  return 0;  /* success */}/*************************************************************************** * ladpad_close()  - Handles the close() of the ladpad device. * * Give back any semaphores taken for the requested access. ***************************************************************************/static int ladpad_close(struct inode *inode, struct file *pfile){  if(pfile->f_mode & FMODE_READ){    up(&ladpad_read_sem);  }  if(pfile->f_mode & FMODE_WRITE){    up(&ladpad_write_sem);  }  /* Log close */  if (debuglvl >= 3) {    printk(KERN_INFO "ladpad closed\n");  }  return 0;}/*************************************************************************** * ladpad_read()  - Read key presses from the keypad * * Transfers the ASCII value of a key press when the user presses a * key.  The keypad scanning is done in a routine attached to a * timer.  The timer routine and this routine communicate using the * Key_Press variable and a wait_queue. * * This routine blocks until the backgound routine detects a new key * press.  Only one keypress is reported at a time. Returns number of * bytes transferred. ***************************************************************************/static ssize_t ladpad_read(        struct file *pfile,   /* points to our file structure */        char __user *buffer,  /* buffer to fill with data */        size_t count,         /* number of bytes requested */        loff_t * offset){  ssize_t retval = 0;           /* Number of bytes transfered */  /* Wait here until a key press is available */  if (Key_Press == (char) 0) {    /* Wait on WaitQ until Key_Press is nonzero */    if(wait_event_interruptible(WaitQ, Key_Press)){      /* Signal caught */      return -ERESTARTSYS;    }  }  /* Deliver ASCII code to the user */  if (Key_Press != (char) 0){    put_user(Key_Press, buffer);    *offset++;    retval = 1;  }  Key_Press = (char) 0;       /* Empty the one-character 'queue' */  /* Log read() */  if (debuglvl >= 3) {    printk(KERN_INFO "ladpad read() returned 0x%02x\n", Key_Press);  }  return retval;}/*************************************************************************** * keypad_scan()  - Timeout function that does a scan of the keypad. * and outputs a single character to the LCD if any are available. * * This routine assumes a four-by-four array of switches.  The output * lines to the keypad are the first four data lines.  The inputs are * bits 3 to 6 in the parallel port status register.  ***************************************************************************/static void keypad_scan(unsigned long ptr){  int   value;          /* value from parallel port status pins */  char  keydown = 0;    /* ASCII value of key pressed */  /* Output a character if any are in the circular buffer */  if (ccnt) {    out44780(cbuf[oindx++]);    oindx = (oindx == CBUFSZ) ? 0 : oindx;    ccnt--;    if (ccnt < CBUFSZ/2) {      wake_up(&SendQ);    }  }  /* Keypad scan puts a zero on one of the first two data    * lines and then looks for a zero on the pins from the   * status port.  The intersection of which data pin and   * which status pin identifies which key was pressed. */  outb(0x02, io_base);               /* put 0 on row 0 */  value = inb(io_base + 1);          /* switch state in bits 3,4 */  if ((value & 0x08) == 0x00)        /* remember: closed=0, open=1 */    keydown = 'C';  if ((value & 0x10) == 0x00)        /* look at switch on column 1 */    keydown = 'Z';  outb(0x01, io_base);               /* put 0 on row 1 */  value = inb(io_base + 1);         if ((value & 0x08) == 0x00)        /* look at switch on column 0 */    keydown = 'E';  if ((value & 0x10) == 0x00)        /* look at switch on column 1 */    keydown = 'D';   /* Shift values for key debounce */  if (last_1 == 0 && last_0 == 0 && keydown != 0 && Key_Press == (char) 0) {    Key_Press = keydown;   /* New key press is available */    wake_up(&WaitQ);  }  last_1 = last_0;  last_0 = keydown;  /* Flash and update LED */  if (led == 0) {    led_state = LED0;  }  else if (led == 0xFF) {    led_state = LED1;  }  else {    led_state =  (led_counter < led) ? LED0 : LED1;    led_counter = (led_counter >= (led * 2)) ? 0 : led_counter + 1;  }  outb((led_state | rs_state | e_state), io_base + 2);  keypad_timer.expires = jiffies + (scan_time * (HZ / 100));  add_timer(&keypad_timer);}/*************************************************************************** * ladpad_poll()  - Indicates if read() or write() will succeed * * This routine returns a bit mask to indicate when a character is * ready to be read.  A write does not block on this device so we * always return that it is writable. ***************************************************************************/static unsigned int ladpad_poll(        struct file *pfile,        poll_table *ppt){  int ready_mask = 0;  /* Add the device's input queue to the provided poll table. */  poll_wait(pfile, &WaitQ, ppt);  /* Add the device's output queue to the provided poll table. */  poll_wait(pfile, &SendQ, ppt);  if (Key_Press != (char) 0) {    ready_mask |= (POLLIN | POLLRDNORM);  }  if (ccnt < CBUFSZ) {    ready_mask |= (POLLOUT | POLLWRNORM);  }  /* Log poll output */  if (debuglvl >= 3) {    printk(KERN_INFO "ladpad: poll returns 0x%x\n", ready_mask);  }  return ready_mask;}/*************************************************************************** * ladpad_write()  - A write to the LCD display or LED * *     Accepts characters from the user for display on the LCD display. * We drop the characters into a circular buffer for output in the timeout * routine. ***************************************************************************/static ssize_t ladpad_write(        struct file *pfile,        const char __user *buffer,        size_t length,        loff_t * offset){  int   ret;                 /* number of bytes output */  int   out_count = 0;       /* byte counter */  int   freecnt;             /* number of free bytes in circurlar buf */  char  next_byte;  /* Wait here until a key press is available */  if (CBUFSZ == ccnt) {    /* Wait on SendQ until output buffer space is available */    if (wait_event_interruptible(SendQ, (CBUFSZ - ccnt))) {      /* Signal caught */      return -ERESTARTSYS;    }  }  /* Compute the amount of free space in the circular buffer */  freecnt = CBUFSZ - ccnt;  /* Accept freecnt bytes or length, whichever is lower */  ret = (freecnt < length) ? freecnt : length;  if (debuglvl >= 3) {    printk(KERN_INFO "ladpad: free=%d len=%d ret=%d in=%d out=%d cnt=%d \n",           freecnt, length, ret, iindx, oindx, ccnt);  }  while (out_count < ret) {    /* The macro get_user returns 0 for success or -EFAULT. */    if(get_user(next_byte, buffer)){      return -EFAULT;    }    cbuf[iindx++] = next_byte;    if (iindx == CBUFSZ) {        iindx = 0;    }    /* Character consumed; update local and user pointers. */    buffer++;    *offset++;    out_count++;  }  ccnt += ret;  /* Return the number of characters read from the buffer */  return ret;}/*************************************************************************** * out44780()  - Output a single character to the 44780 LCD display. * * This routine also handles command output to the LCD, and the setting * of the LED flash frequency. *     This routine implements a state machine to indicate how to  * interpret the next byte read.  A state=NORM means that the next character * is to be sent directly to LCD display.  If state=CMD, the next character * is a command to send to the LCD display.  If state=LED, the next * character is a command for the LED. *     The very low power controller on the LCD display can accept commands * and characters at a fairly slow rate so we output a single character * at each timeout. ***************************************************************************/static void out44780(        unsigned char outchar){  if (input_state == LAD_LED) {    led = outchar;    input_state = LAD_NORM;    if (debuglvl >= 3) {      printk(KERN_INFO "ladpad: led set = 0x%02x\n", led);    }  }  else {    if (outchar == LADPAD_CMD) {      input_state = LAD_CMD;      rs_state = RSCMD;    }    else if (outchar == LADPAD_LED) {      input_state = LAD_LED;    }    else {      /* send char to LCD display */      outb(outchar, io_base);      e_state = E1;      outb((led_state | rs_state | e_state), io_base + 2);      udelay(2);      e_state = E0;      outb((led_state | rs_state | e_state), io_base + 2);      if (debuglvl >= 3) {        if ((outchar >= ' ') && (outchar <= '~'))          printk(KERN_INFO "ladpad:  char 0x%02x '%c'\n", outchar, outchar);        else          printk(KERN_INFO "ladpad:  char 0x%02x\n", outchar);      }      /* After sending anything to the LCD we go back to LAD_NORM */      input_state = LAD_NORM;      rs_state = RSDATA;    }  }}module_init(ladpad_init);module_exit(ladpad_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -