關於我自己

2016年1月1日 星期五

linux driver sample

main.c main.h sub.c sub.h test.c ==> wdt.ko test
這範例是註冊一個class並由系統提供空的掛載點
如果要修改只需要把紫色部分和control 修改掉即可。
Makefile寫的不是很好..恩..


driver       是在kernel space
一般程式 是在user space
OS開機時候可以設定kernel space star address


Linux driver有分:
-內建在系統中
-開機後啟動(如果牽涉到DMA可能會有機率性的拿不到連續實體記憶體buffer)


driver的好處:
多個user app都想控制同一個硬體

注意:
掛載時候有些範例會用mknod 並且指定掛載點(0-255任選)
這方法可用但是不好,
掛在點如果已經有裝置存在會掛載不上去
因此要改由系統提供沒人用的掛載代號(0-255)


Makefile

#------------#
#   Project  #
#------------#

#project name do not same CFILES file name
PROJECT := wdt
TEST    := test
Help    := help
UNINSTALLFILE:=uninstall

#add your any file
CFILES  := main.c sub1.c



#Detect Dymaic D_MAJOR
D_MAJOR :=$(shell grep $(PROJECT) /proc/devices | awk '{print $$1;}')

#Total Minor 1-4
MINOR_DEV_TOTAL :=1

#---------------#
#Global Variable#
#---------------#
KDIR  := /lib/modules/$(shell uname -r)/build
KVERSION := $(shell uname -r)
PWD      := $(shell pwd)
DEV_PATH :=/dev/$(PROJECT)
LIBS  :=
CFLAGS:=
#---------------#
#   Other File  #
#---------------#
CONFFILE    :=project.h


#---------------------------------------#
#compiler                               #
#---------------------------------------#
#-not change-#
obj-m           := $(PROJECT).o


#-not change-#
$(PROJECT)-objs := $(CFILES:.c=.o)





#----------------------#
#          All         #
#----------------------#
all: $(UNINSTALLFILE).sh $(PROJECT) $(TEST) $(Help)

$(PROJECT):
ifeq ($(USER),root)
 @echo  "#define DEV_PATH   \"$(DEV_PATH)\""          >> $(CONFFILE)
 @echo  "#define DRIVER_NAME \"$(PROJECT)\""          >> $(CONFFILE)
 @echo  "#define MINOR_DEV_TOTAL $(MINOR_DEV_TOTAL)"  >> $(CONFFILE)
 @echo  " "                                           >> $(CONFFILE)
 @$(MAKE) -s -C $(KDIR) M=$(PWD) modules
else
 #echo USER is not root!!
endif




#----------------------#
#  install             #
#----------------------#
install : $(PROJECT).ko $(UNINSTALLFILE).sh
 @cp -f $(UNINSTALLFILE).sh _$(UNINSTALLFILE).sh
ifeq (,$(findstring $(PROJECT),$(shell lsmod | grep $(PROJECT))))
  ifeq ($(wildcard /lib/modules/$(PROJECT)),)
  @mkdir -p /lib/modules/$(PROJECT)
  @cp -f $(PROJECT).ko /lib/modules/$(PROJECT)
  @insmod /lib/modules/$(PROJECT)/$(PROJECT).ko
  endif
  ifeq (,$(findstring $(PROJECT).ko,$(shell cat  /etc/rc.local | grep $(PROJECT).ko)))
  @echo insmod /lib/modules/$(PROJECT)/$(PROJECT).ko >> /etc/rc.local
  endif
else
 @echo Please run ./uninstall to remove driver
endif





#----------------------#
#  uninstall           #
#----------------------#
$(UNINSTALLFILE).sh:
 @echo rm -rf  /lib/modules/$(PROJECT)    >> $(UNINSTALLFILE).sh
 @echo rm -f   /dev/$(PROJECT)0           >> $(UNINSTALLFILE).sh
 @#@echo rm -f   /dev/$(PROJECT)1         >> $(UNINSTALLFILE).sh
 @echo rmmod  $(PROJECT)                  >> $(UNINSTALLFILE).sh


.uninstall:
ifeq ($(wildcard /lib/modules/$(PROJECT)),"/lib/modules/$(PROJECT)")
 @rm -rf  /lib/modules/$(PROJECT)
endif

ifeq (   $(findstring "$(PROJECT)" , $(shell lsmod) ) , $(PROJECT))
 rmmod -vf  $(PROJECT)       
endif


#----------------------#
#       Test           #
#----------------------#
$(TEST): $(TEST).o
 gcc -o $@ $(TEST).o -pthread -Wall -O2


#----------------------#
#       Help           #
#----------------------#
$(Help):
 @echo    Joe.Chang 02/02/2015                         
 @echo //----------------------------------------------//
 @echo "//                   help                       //"
 @echo //----------------------------------------------//
 @echo 1. make all       make Project.ko  and test     
 @echo 2. make install   install driver                 
 @echo 3. ./uninstall.sh only clean run-time status     
 @echo 4. make clean     only clean build file         
 @echo                                                 
 @echo If U get Error:                                 
 @echo A. ./uninstall.sh ,                             
 @echo B. make clean                                   


#---------------------------------------#
#              Clean  Build file        #
#---------------------------------------#
clean:
ifeq ($(wildcard /lib/modules/$(PROJECT)),)
 @$(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
 @rm -f $(CONFFILE) $(TEST) $(UNINSTALLFILE).sh
 @rm -f *.bak
else
 @echo make clean is for clean module buld
 @echo
 @echo "error: Please Run ./uninstall before make clean."
 @echo "(Note: If you lose \"uninstall.sh\" try [./_uninstall.sh])"
endif


macro.h
#ifndef H_MARCO
#define H_MARCO

//Strize
#define _STR(s) #s
#define STR(s) _STR(s)

#define _DEV_CAT #s#%%d
#define DEV_CAT(s) _DEV_CAT(s)
#endif


Driver_API(main.h)
#ifndef H_MAIN
#define H_MAIN

#include <linux/ioctl.h>


//first char descritp your driver
#define MAGIC_CHAR 'w'


/* Set  watchdog timer */
#define IOCTL_WDT_TIMER_SET            _IOW(MAGIC_CHAR,  1, int)


/* Start/Stop Watchdog timer */
#define IOCTL_WDT_START_STOP            _IOW(MAGIC_CHAR, 2, int)




#endif //H_MAIN

Driver_method(main.c)
#include <linux/module.h>
#include <linux/kernel.h>

/*init device*/
#include <linux/kdev_t.h>  /* MKDEV*/
#include <linux/cdev.h>    /* MKDEV*/
#include <linux/device.h>  /* class_create  :auto-mknod*/


/*file system*/
#include <linux/fs.h>      /*struct file_operations imajor*/
#include <linux/sched.h>    /*current*/
#include <asm/current.h>    /*current*/
#include <asm/uaccess.h>   /* copy from user*/



#include "project.h"
#include "main.h"
#include "sub1.h"
#include "marco.h"



#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
#else
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#endif

//--------------------------//
//    MAIN DEFINE           //
//--------------------------//
//register driver
#define DRIVER_AUTHOR        "Joe Chang <joe_chang@Intel.com.tw"
#define DRIVER_DESCRIPTION   "A sample driver"
#define DRIVER_VERSION       1.00

#ifndef THIS_LICENCE
#define THIS_LICENCE     "Dual BSD/GPL"
#endif


#ifndef DRIVER_NAME
#define DRIVER_NAME  "sample"
#endif

#define DRIVER_NAME_BUFFER 32


#ifndef MINOR_DEV_TOTAL
#define MINOR_DEV_TOTAL   1
#endif

#if    MINOR_DEV_TOTAL == 0
#undef MINOR_DEV_TOTAL
#define MINOR_DEV_TOTAL 1
#endif



//--------------------------//
//    User Variable  Define //
//--------------------------//
//static int wdt_timer = 0;



//--------------------------//
//    routine Variable      //
//--------------------------//
/* lock device prevent muti-uers */
static  int lock       = 0;
static  int dev_major  = 0;
static  int dev_minor  = 0;

static unsigned int number_of_devices = MINOR_DEV_TOTAL; //if 3 ,mean /dev/sample0~2
static struct cdev sample_cdev;


static struct class *this_class = NULL;
static dev_t  class_sample_dev[MINOR_DEV_TOTAL];



//--------------------------//
//    ioctrl Variable       //
//--------------------------//
static  int wdt_timer = 0;


//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : sample_probe
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
static int sample_probe(struct inode * inode, struct file * file)
{

printk("%s major%d minor%d(pid%d)\n", __func__ , imajor(inode), iminor(inode)
, current->pid);
// one one process can control this device at same time
if(lock) return -EBUSY;
//lock = 1;


return 0;

}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : sample_remove
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
static int sample_remove(struct inode * inode, struct file * file)
{
//Free Device
lock = 0;

return 0;

}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : sample_ioctl
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//
//  Joe: driver data is at kernel space space block !!
//
//  A:
//  copy data of "user space memory " to kernel space memory
//  static inline __must_check long __copy_from_user(void *to,const void __user * from, unsigned long n)
//
//  copy_to_user();
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) )
static int sample_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
#else
static long sample_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#endif
{

int value;


if( copy_from_user(&value, (void *)arg, sizeof(value)) )
return -EFAULT;



  switch(cmd)
        {
       
case IOCTL_WDT_TIMER_SET:
                      wdt_timer=value;
                      if ( (wdt_timer < 0 ) || (wdt_timer > 255))
                        {
                          printk(KERN_ERR "wdt_drv error: Invalid time value\n");
                            wdt_timer=0;
                            return -EOPNOTSUPP;
                        }
                     break;

case IOCTL_WDT_START_STOP:
if(value == WDT_START )
nct6776_wdt_start(wdt_timer);
else if(value == WDT_STOP)
nct6776_wdt_stop();
else 
return -EOPNOTSUPP;
break;

default:
                 return -EOPNOTSUPP;
                 break;
        }
     

return 0;
}


//--------------------------------------------//
//    file_operations protocol                //
//--------------------------------------------//
/* http://www.faqs.org/docs/kernel/x571.html */
static const struct file_operations sample_protocol = {
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) )
.ioctl = sample_ioctl,
#else
.unlocked_ioctl = sample_ioctl,
#endif
.open = sample_probe,
.release = sample_remove
};







//--------------------------//
//    remove device         //
//--------------------------//
void
remove_device(void)
{
dev_t remove_dev = MKDEV( dev_major , 0 );

cdev_del(&sample_cdev);
unregister_chrdev_region( remove_dev , number_of_devices );
}


//--------------------------//
//    remove class          //
//--------------------------//
void
remove_class(void)
{
int i;


for( i = 0 ; i < number_of_devices ; i ++)
{
 device_destroy( this_class , class_sample_dev[i] );
}
class_destroy(this_class);

}

//--------------------------//
//    free driver    API    //
//--------------------------//
void sample_exit(void)
{

  remove_class();            
  remove_device();


lock = 0;

printk("%s  Sample Driver -- Unloaded\n", DRIVER_NAME);
printk("=====================================================\n");
}


//--------------------------//
//    init driver           //
//--------------------------//

int
init_register_driver(void)
{
int ret=0,newMajor=0;
dev_t dev = MKDEV(dev_major ,0  );

  printk("number_of_devices %d\n",number_of_devices  );

 
  /*Get Dynamic major number*/
  /*  https://www.kernel.org/doc/htmldocs/kernel-api/API-alloc-chrdev-region.html   */
  ret = alloc_chrdev_region(&dev , 0 ,number_of_devices , DRIVER_NAME );
  if(ret)
  goto error_alloc;

 
  newMajor = MAJOR(dev);
  //Check, is major change?
  if( dev_major != newMajor){
  printk("%s Major %d is changed to %d\n",DRIVER_NAME,dev_major,newMajor );
  dev_major = newMajor;
  }


  /*define file_oprations */
  cdev_init(&sample_cdev,&sample_protocol);
  sample_cdev.owner = THIS_MODULE;
  sample_cdev.ops   = &sample_protocol;

  /*  Register driver in Kernel */
  /*  int cdev_add(struct cdev *cdev ,dev_t dev , unsigned count);  */
  ret = cdev_add(&sample_cdev, MKDEV(dev_major,dev_minor), number_of_devices );
  if(ret)
  goto err_cdev_add;


return 0;


err_cdev_add:
    printk("err_cdev_add\n");
    unregister_chrdev_region(dev,number_of_devices);
      return -1;



error_alloc:
    printk("error_alloc\n");
    return -1;
}


//--------------------------//
//    init driver   FS      //
//--------------------------//

int
init_register_file_system(void)
{
struct device *class_dev;
char   minor_name[DRIVER_NAME_BUFFER];
int    i;


  /*Register Class in filesystem*/
  this_class = class_create( THIS_MODULE,DRIVER_NAME);
  if(IS_ERR(this_class))
  goto error_class;





  /*mount fs dev in filesystem*/
  /* struct device * device_create ( struct class * class,struct device * parent,dev_t devt,void * drvdata,const char * fmt,...) */
  for( i = 0 ; i <  number_of_devices ; i ++)
  {
   class_dev = NULL;
   dev_minor = i;

  strcpy(minor_name ,DRIVER_NAME);
  strcat(minor_name,"%d");
 
  class_sample_dev[dev_minor] = MKDEV( dev_major, dev_minor);
   
//   class_dev = device_create (this_class,NULL,class_sample_dev[dev_minor],NULL, driver_name ,dev_minor);
class_dev = device_create (this_class,NULL,class_sample_dev[dev_minor],NULL, minor_name ,dev_minor);
  if(class_dev == NULL )
  {
  printk(KERN_ERR  "%s driver(major%d minor%d) installed fail.\n",minor_name ,dev_major, dev_minor);
  goto err_cdev_add;
  }
  else
      printk("%s Driver(major%d minor%d) installed at /sys/class/%s/%s%d.\n",DRIVER_NAME, dev_major, dev_minor,DRIVER_NAME ,DRIVER_NAME,dev_minor);
  }
 



return 0;
 
 
error_class:
    printk("error_class\n");
    return -1;
   
err_cdev_add:
    printk(KERN_ALERT "%s driver(major %d) installed fail.\n",DRIVER_NAME ,dev_minor);
    remove_class();
      return -1;
}

//--------------------------//
//    init API              //
//--------------------------//
int sample_init(void)
{

int ret = 0;
 
    printk("=====================================================\n");
    printk("Sample %s Driver: init\n",DRIVER_NAME);

    ret = init_register_driver();
  if(ret < 0 )
  goto init_register_driver_error;

init_register_file_system();
  if(ret < 0 )
  goto init_register_file_system_error;

    printk("%s Driver init pass\n", DRIVER_NAME );
 

return 0;


init_register_driver_error:
printk("Sample %s Driver: init driver fail \n",DRIVER_NAME);
  return ret;
 
init_register_file_system_error:  
remove_device();
remove_class();
printk("Sample %s Driver: init fs fail \n",DRIVER_NAME);
  return ret;
}




//-------------//
//Module define//
//-------------//
/*
 * The following license idents are currently accepted as indicating free
 * software modules
 *
 *      "GPL"                           [GNU Public License v2 or later]
 *      "GPL v2"                        [GNU Public License v2]
 *      "GPL and additional rights"     [GNU Public License v2 rights and more]
 *      "Dual BSD/GPL"                  [GNU Public License v2
 *                                       or BSD license choice]
 *      "Dual MIT/GPL"                  [GNU Public License v2
 *                                       or MIT license choice]
 *      "Dual MPL/GPL"                  [GNU Public License v2
 *                                       or Mozilla license choice]
 *
 * The following other idents are available
 *
 *      "Proprietary"                   [Non free products]
 *
 * There are dual licensed components, but when running with Linux it is the
 * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
 * is a GPL combined work.
 *
 * This exists for several reasons
 * 1.   So modinfo can show license info for users wanting to vet their setup
 *      is free
 * 2.   So the community can ignore bug reports including proprietary modules
 * 3.   So vendors can do likewise based on their own policies
 */
MODULE_LICENSE(THIS_LICENCE);
/* Author, ideally of form NAME[, NAME]*[ and NAME] */
MODULE_AUTHOR(DRIVER_AUTHOR);

 /* What your module DESCRIPTION. */
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);


//---------//
//  Module //
//---------//
module_init(sample_init);
module_exit(sample_exit);


Chip_Control_API(sub.h)
#if __linux
#define inportb(x) inb_p(x)
#define outportb(x, y) outb_p(y, x)
#define inportl(x) inl_p(x)
#define inportw(x) inw_p(x)
#define outportl(x, y) outl_p(y, x)
#endif 

/* Start/Stop WDT */
#define WDT_START                       0
#define WDT_STOP                        1




void nct6776_config_enter(void);
void nct6776_config_exit(void);


unsigned char nct6776_read_reg (int LDN, int reg);
void nct6776_write_reg(int LDN, int reg, int value);

void nct6776_wdt_start(int timer);
void nct6776_wdt_stop(void);

Chip_control_method(sub.c)

#if __linux
#define delay(x) usleep(x)
#endif



//#ifdef MODULE
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/delay.h>
#undef delay
#define delay(x) mdelay(x)
#undef fprintf
#define fprintf(S, A)  printk(A)
//#endif //MODULE

//#ifdef KLD_MODULE
//#include <sys/types.h>
//#include <sys/param.h>
//#include <sys/systm.h>
//#include <sys/malloc.h>
//#include <sys/kernel.h>
//#include <sys/bus.h>
//#include <sys/errno.h>
//#include <machine/bus.h>
//#include <machine/resource.h>
//#endif



/* local include file */
#include "sub1.h"





#define INDEX_PORT 0x2E
#define DATA_PORT  0x2F


//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : nct6776_config_enter
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void 
nct6776_config_enter(
void
){
        outportb(INDEX_PORT, 0x87); // Must Do It Twice
        outportb(INDEX_PORT, 0x87);
        return;
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : nct6776_config_exit
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void 
nct6776_config_exit(
void
){
        outportb(INDEX_PORT, 0xAA);
        return;
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : main
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
unsigned char 
nct6776_read_reg(
int LDN, 
int reg
){
        unsigned char tmp = 0;


        nct6776_config_enter();
        outportb(INDEX_PORT, 0x07); // LDN Register
        outportb(DATA_PORT, LDN); // Select LDNx
        outportb(INDEX_PORT, reg); // Select Register
        tmp = inportb( DATA_PORT ); // Read Register
        nct6776_config_exit();
        return tmp;
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : nct6776_write_reg
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void 
nct6776_write_reg(
int LDN, 
int reg, 
int value
){
        nct6776_config_enter();
        outportb(INDEX_PORT, 0x07); // LDN Register
        outportb(DATA_PORT, LDN); // Select LDNx
        outportb(INDEX_PORT, reg); // Select Register
        outportb(DATA_PORT, value); // Write Register
        nct6776_config_exit();
        return;
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : nct6776_wdt_start
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void 
nct6776_wdt_start(
int timer
){
unsigned char tmp;

nct6776_config_enter();

/* clear status bit */
tmp=nct6776_read_reg(0x08, 0xf7);
tmp &= ~(0x10);
nct6776_write_reg(0x08, 0xf7, tmp);

/* clear timeout value */
nct6776_write_reg(0x08, 0xf6, 0x00);

/* set to count with second */
tmp=nct6776_read_reg(0x08, 0xF5);
tmp &= ~(0x08);
nct6776_write_reg(0x08, 0xF5, tmp);


/* set WDT Reset Event */
tmp=nct6776_read_reg(0x08, 0xF7);
tmp = (0x00);
nct6776_write_reg(0x08, 0xF7, tmp);

/* Set function enable */
tmp=nct6776_read_reg(0x08,0x30);
tmp |= 0x01;
nct6776_write_reg(0x08, 0x30, tmp);

/* fill in timeout value */
nct6776_write_reg(0x08, 0xf6, timer);
nct6776_config_exit();
return;
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : nct6776_wdt_stop
// INPUT      : 
// OUTPUT     :
// DESCRIPTION: 
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void 
nct6776_wdt_stop(
void
){
nct6776_config_enter();

/* stop timer */
nct6776_write_reg(0x08, 0xf6, 0);
nct6776_config_exit();
}







test.c
#include <stdio.h>
#include <unistd.h> /*close*/
#include <fcntl.h> /*close*/

#include <unistd.h> //1s=sleep(1) 1s=usleep(1000000)
// < -- http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html -- >
#include <pthread.h>     // Muti-thread Library UNIX only


#include <string.h> /*memset*/
#include "project.h"
#include "main.h"
#include "sub1.h"


#ifndef DEV_PATH
#define DEV_PATH "/dev/wdt_drv"
#endif


#ifndef MINOR_DEV_TOTAL
#define MINOR_DEV_TOTAL 1
#endif


#define delay(x) usleep(x)




//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : help
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void help(char* argv0)
{
        printf("%s -t xxx     (Set   Watchdog Timer 1-255 seconds)\n", argv0);
        printf("%s -auto    (Auto Start Watchdog Timer)\n"         , argv0);
        printf("%s -start   (Start Watchdog Timer)\n"              , argv0);
        printf("%s -stop    (Stop  Watchdog Timer)\n"              , argv0);
}



//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// Procedure      : Auto_Thread
// input          : Function PTR
// output         :
// Description    :

//-----------------------------------------------------------------------------------------------//
//<Intel_START>          
void
Auto_Thread(
void (*Function)(void *)
){
int        status;
pthread_t  thread1;
  char       gch;
  void      *fptr;

        fptr = Function;

    status = -1;


status = pthread_create(&thread1, NULL, fptr, NULL);
if(status == 1)
{
printf("Create Thread Fail\n");
return;
}
else
printf("Create Thread Success-->  Working in back \n");
printf("Press Q to exit\n");

//Wait User press 'Q'
do{
  gch = getchar();

    if(gch == 'q')
{
printf("Cancel!!");
pthread_cancel(thread1);//The pthread_cancel() function shall request that thread be  canceled
   }
  }while(  (gch != 'q') && (gch != 'Q' ) );

      pthread_join(thread1,NULL);//Wait Thread finish
   

//Wait thread finish
  pthread_join(thread1,NULL);//Wait Thread finish
}



//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : start_wdt
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
void auto_start_wdt(){
        int devfd;
        int value;
     
iopl(3);
     
     
     
     
        do{
       
         printf("Press Q to exit\n");
        devfd = open(DEV_PATH, O_RDONLY);
        if( devfd != -1)
        {
        printf("Start WDT Timer....");
        value = WDT_START;
              if( ioctl(devfd, IOCTL_WDT_START_STOP, &value) != 0)
                        printf("Fail\n");
              else
                        printf("OK\n");
         }else
          printf("Open Fail\n");
         
        close(devfd);
        usleep(500000);
        }while(1);
     
        iopl(0);      
}

//<Intel_START>
//-----------------------------------------------------------------------------------------------//
// FUNCTION   : main
// INPUT      :
// OUTPUT     :
// DESCRIPTION:
//-----------------------------------------------------------------------------------------------//
//<Intel_END>
int main( int argc, char** argv )
{
        int devfd[MINOR_DEV_TOTAL];
        char files[512];
     
     
        char *dev_name="/dev/sample";
        int value;
int Seladdress;
int i;
     


for( i = 0 ; i < MINOR_DEV_TOTAL ; i++ )
{
memset(files,0,512);
snprintf( files , sizeof(files) ,"%s%d" ,dev_name,i);
  devfd[i] = open(files, O_RDONLY);
  if(devfd[i] == -1 )
  printf("Open \"%s\" Fail\n",files);
  else
  printf("Open \"%s\" OK\n",files);
 
}


sleep(10);


for( i = 0 ; i < MINOR_DEV_TOTAL ; i++ )
{
printf("Device %d Close\n",i);
 close(devfd[i]);
}

/*
        if ( argc < 2) {
                help(argv[0]);
                return -1;
        }


iopl(3);
        devfd = open(DEV_PATH, O_RDONLY);
        if(devfd == -1)
        {
                printf("Can't open %s\n",DEV_PATH);
                iopl(0);
                return -1;
        }
     
     
     
if ( !strcmp(argv[1], "-t"))
{
                int tmp;
                if (argc !=3) {
                        printf("No timer input\n");
                        close(devfd);
                        iopl(0);
                        return -1;
                }
             
                tmp = atoi(argv[2]);
                if ( (tmp < 1) || (tmp > 255)) {
                        printf("Wrong timer value, please input range (1-255)\n");
                        close(devfd);
                        return -1;
                }
             

                printf("Set WDT Timer....");
                if( ioctl(devfd, IOCTL_WDT_TIMER_SET, &tmp) != 0)
                        printf("Fail\n");
                else
                        printf("OK\n");

        }
  else if ( !strcmp(argv[1], "-start")) {
                printf("Start WDT Timer....");
value = WDT_START;
                if( ioctl(devfd, IOCTL_WDT_START_STOP, &value) != 0)
                        printf("Fail\n");
                else
                        printf("OK\n");
        }
        else if ( !strcmp(argv[1], "-auto")) {
        close(devfd);
        printf("Please Setting Time Before Auto Start!!\n");
        Auto_Thread(auto_start_wdt);
        }
  else if ( !strcmp(argv[1], "-stop")) {
                printf("Stop WDT Timer....");
value = WDT_STOP;
                if( ioctl(devfd, IOCTL_WDT_START_STOP, &value) != 0)
                        printf("Fail\n");
                else
                        printf("OK\n");
        }


else {
printf("Unknow Error!!\n");
                help(argv[0]);
}


        close(devfd);
        iopl(0);
        return 0;
*/
}