亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? ds1307.c

?? RTC時鐘驅動 RTC時鐘驅動
?? C
字號:
/*
 * Brian Kuschak <bkuschak@yahoo.com>
 *
 * I2C driver for Dallas (Maxim) DS1307 Real Time Clock.
 * Some code 'borrowed' from the DS1302 driver.
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-ppc405.h>
#include <linux/i2c-ppc405adap.h>
#include <asm/uaccess.h>
#include <asm/rtc.h>
#include <linux/proc_fs.h>

#define RTC_MAJOR_NR 121 /* local major, change later */

static const char ds1307_name[] = "ds1307";

/* The I2C address we scan looking for DS1307
 */
static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x68, 0x68, I2C_CLIENT_END }; 
I2C_CLIENT_INSMOD;

static struct i2c_driver rtc_i2c_driver;
static struct i2c_client client_template;
static struct i2c_client *ds1307_client;

static unsigned char days_in_mo[] = 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

static void rtc_i2c_init_client(struct i2c_client *pclient);

static void inc_use(struct i2c_client *client)
{
#ifdef MODULE
	MOD_INC_USE_COUNT;
#endif
}

static void dec_use(struct i2c_client *client)
{
#ifdef MODULE
	MOD_DEC_USE_COUNT;
#endif
}

/* We get here after scanning the I2C device at one of the DS1307 addresses.
 */
static int rtc_i2c_detect_rtc(struct i2c_adapter *adap, int addr, 
				unsigned short flags, int kind)
{
	int err;
	char c = 0;
	int found = 0;
	struct i2c_client *pclient;

	if (!(pclient = (struct i2c_client *)kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
	{
		printk("ds1307: Driver failed memory allocation\n");
		return -ENOMEM;
	}
	memcpy(pclient, &client_template, sizeof(struct i2c_client));
	pclient->addr = addr;
	pclient->adapter = adap;

	if(i2c_master_send(pclient, &c, 1) == 1)
	{
		if(i2c_master_recv(pclient, &c, 1) == 1)
		{
			printk("ds1307: I2C Real-Time-Clock detected at addr 0x%x\n", pclient->addr);
			found = 1;
		}
	}
	if(found)
	{
		if((err = i2c_attach_client(pclient)))
		{
			printk("ds1307: failed to attach client\n");
			kfree(pclient);
			return err;
		}
		rtc_i2c_init_client(pclient);
	}
	else
	{
		kfree(pclient);
	}
	return 0;
}

static int detach_client(struct i2c_client *client)
{
	return 0;
}

static int i2c_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
	return -1;
}

static int attach_adapter(struct i2c_adapter *adap)
{
	/* Look for the PowerPC adapter */
	if(adap->id == (I2C_ALGO_PPC405 | I2C_HW_PPC405))
		return i2c_probe(adap, &addr_data, rtc_i2c_detect_rtc);

	return 0;
}

static int ds1307_readreg(struct i2c_client *pclient, int reg)
{
	unsigned char c = reg;
	
	if(!pclient)
		return 0;

	/* set pointer register */
	if(i2c_master_send(pclient, &c, 1) == 1)
	{
		/* read data register */
		if(i2c_master_recv(pclient, &c, 1) == 1)
		{
			return c;
		}
	}
	return 0;
}

static int ds1307_writereg(struct i2c_client *pclient, int val, int reg)
{
	unsigned char buf[2];
	
	if(!pclient)
		return 0;

	buf[0] = reg;
	buf[1] = val;

	if(i2c_master_send(pclient, buf, sizeof(buf)) == sizeof(buf))
	{
		return val;
	}
	return 0;
}

static void rtc_i2c_init_client(struct i2c_client *pclient)
{
	int val;

	/* Datasheet says the oscillator may not be enabled on the first powerup. 
	 * Enable it if necessary.
	 */
	if((val = ds1307_readreg(pclient, RTC_SECONDS)) & 0x80)
		ds1307_writereg(pclient, (val & ~0x80), RTC_SECONDS);

	ds1307_client = pclient;	 /* hack! */
}

void
get_rtc_time(struct rtc_time *rtc_tm) 
{
	unsigned long flags;
	struct i2c_client *pclient = ds1307_client;	/* hack! */
		
	save_flags(flags);
	cli();

	rtc_tm->tm_sec = (ds1307_readreg(pclient, RTC_SECONDS) & 0x7f);
	rtc_tm->tm_min = (ds1307_readreg(pclient, RTC_MINUTES) & 0x7f);
	rtc_tm->tm_hour = (ds1307_readreg(pclient, RTC_HOURS) & 0x3f);
	rtc_tm->tm_mday = (ds1307_readreg(pclient, RTC_DAY_OF_MONTH) & 0x3f);
	rtc_tm->tm_mon = (ds1307_readreg(pclient, RTC_MONTH) & 0x1f);
	rtc_tm->tm_year = ds1307_readreg(pclient, RTC_YEAR);

	restore_flags(flags);
	
	BCD_TO_BIN(rtc_tm->tm_sec);
	BCD_TO_BIN(rtc_tm->tm_min);
	BCD_TO_BIN(rtc_tm->tm_hour);
	BCD_TO_BIN(rtc_tm->tm_mday);
	BCD_TO_BIN(rtc_tm->tm_mon);
	BCD_TO_BIN(rtc_tm->tm_year);

	/*
	 * Account for differences between how the RTC uses the values
	 * and how they are defined in a struct rtc_time;
	 */

	if (rtc_tm->tm_year <= 69)
		rtc_tm->tm_year += 100;

	rtc_tm->tm_mon--;
}

/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date) */

static int
rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	  unsigned long arg) 
{
        unsigned long flags;
	struct i2c_client *pclient = ds1307_client;	/* hack! */

	switch(cmd) {
		case RTC_RD_TIME:	/* Read the time/date from RTC	*/
		{
			struct rtc_time rtc_tm;
						
			get_rtc_time(&rtc_tm);						
			if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
				return -EFAULT;	
			return 0;
		}

		case RTC_SET_TIME:	/* Set the RTC */
		{
			struct rtc_time rtc_tm;
			unsigned char mon, day, hrs, min, sec, leap_yr;
			unsigned int yrs;
#if 1
			if (!suser())
				return -EACCES;
#endif			
			if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
				return -EFAULT;    	

			yrs = rtc_tm.tm_year + 1900;
			mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
			day = rtc_tm.tm_mday;
			hrs = rtc_tm.tm_hour;
			min = rtc_tm.tm_min;
			sec = rtc_tm.tm_sec;
			
			
			if ((yrs < 1970) || (yrs > 2069))
				return -EINVAL;

			leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));

			if ((mon > 12) || (day == 0))
				return -EINVAL;

			if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
				return -EINVAL;
			
			if ((hrs >= 24) || (min >= 60) || (sec >= 60))
				return -EINVAL;

			if (yrs >= 2000)
				yrs -= 2000;	/* RTC (0, 1, ... 69) */
			else
				yrs -= 1900;	/* RTC (70, 71, ... 99) */

			BIN_TO_BCD(sec);
			BIN_TO_BCD(min);
			BIN_TO_BCD(hrs);
			BIN_TO_BCD(day);
			BIN_TO_BCD(mon);
			BIN_TO_BCD(yrs);

			save_flags(flags);
			cli();
			ds1307_writereg(pclient, yrs, RTC_YEAR);
			ds1307_writereg(pclient, mon, RTC_MONTH);
			ds1307_writereg(pclient, day, RTC_DAY_OF_MONTH);
			ds1307_writereg(pclient, hrs, RTC_HOURS);
			ds1307_writereg(pclient, min, RTC_MINUTES);
			ds1307_writereg(pclient, sec, RTC_SECONDS);
			restore_flags(flags);

			/* notice that at this point, the RTC is updated but the kernel
			 * is still running with the old time. you need to set that
			 * separately with settimeofday or adjtimex.
			 */
			return 0;
		}
		default:
			//return -ENOIOCTLCMD;
			return -EINVAL;
	}
}

/*
 *	Info exported via "/proc/rtc".
 */

static int proc_read_rtc_status(char *page, char **start, off_t off,
				int count, int *eof, void *data)
{
	char *out = page;
	int len;
	struct rtc_time tm;

	get_rtc_time(&tm);

	/*
	 * There is no way to tell if the luser has the RTC set for local
	 * time or for Universal Standard Time (GMT). Probably local though.
	 */

	out += sprintf(out,
		"rtc_time\t: %02d:%02d:%02d\n"
		"rtc_date\t: %04d-%02d-%02d\n",
		tm.tm_hour, tm.tm_min, tm.tm_sec,
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);

	len = out - page;
	len -= off;
	if (len < count) {
		*eof = 1;
		if (len <= 0)
			return 0;
	} else
		len = count;
	*start = page + off;
	return len;
}


/*
 *	The various file operations we support.
 */

static struct file_operations rtc_fops = {
        owner:          THIS_MODULE,
        ioctl:          rtc_ioctl,	
}; 


/* just probe for the RTC and register the device to handle the ioctl needed */

static __init int ds1307_init(void) 
{ 
	int             res;

	if ((res = i2c_add_driver(&rtc_i2c_driver)))
	{
		printk("ds1307: I2C driver registration failed\n");
		return res;
	}
	if (register_chrdev(RTC_MAJOR_NR, ds1307_name, &rtc_fops)) {
		printk("unable to get major %d for %s\n", RTC_MAJOR_NR, ds1307_name);
		return -1;
	}
	create_proc_read_entry (ds1307_name, 0, NULL, proc_read_rtc_status, NULL);
	return 0;
}

static __exit void ds1307_cleanup(void)
{
	int             res;

	remove_proc_entry(ds1307_name, 0);

	if (unregister_chrdev(RTC_MAJOR_NR, ds1307_name)) {
		printk("unable to unregister %s\n", ds1307_name);
	}
	if ((res = i2c_del_driver(&rtc_i2c_driver)))
	{
		printk("ds1307: I2C driver deregistration failed, "
			       "module not removed.\n");
	}
}

static struct i2c_driver rtc_i2c_driver =
{
	name:		"I2C driver for DS1307 RTC",
	id:		I2C_DRIVERID_DS1307,
	flags:		I2C_DF_NOTIFY,
	attach_adapter:	attach_adapter,
	detach_client:	detach_client,
	command:	i2c_command,
	inc_use:	inc_use,
	dec_use:	dec_use
};

static struct i2c_client client_template = 
{
	name:		"DS1307 I2C",
	id:		I2C_DRIVERID_DS1307,
	data:		NULL,
	flags:		0,
	addr:		0,
	adapter:	NULL,
	driver:		&rtc_i2c_driver
};

MODULE_DESCRIPTION("I2C driver for DS1307 RTC");

module_init(ds1307_init);
module_exit(ds1307_cleanup);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
麻豆精品在线播放| 老司机精品视频一区二区三区| 久久夜色精品国产欧美乱极品| 色呦呦国产精品| 99久久精品免费看| av电影天堂一区二区在线观看| 国产91丝袜在线18| 成人av中文字幕| 99久久婷婷国产| 91精彩视频在线观看| 在线看日韩精品电影| 欧美视频你懂的| 6080午夜不卡| 日韩视频在线你懂得| 久久久精品免费观看| 国产视频一区二区在线观看| 国产免费成人在线视频| 中文字幕精品一区| 亚洲人成网站精品片在线观看| 亚洲视频综合在线| 亚洲一本大道在线| 欧美96一区二区免费视频| 美女爽到高潮91| 国产精品99久久久久久久vr| 成人免费毛片片v| 色噜噜狠狠一区二区三区果冻| 一本色道a无线码一区v| 欧美日韩国产高清一区二区三区 | 久久综合九色综合欧美就去吻| 久久一留热品黄| 亚洲色图自拍偷拍美腿丝袜制服诱惑麻豆| 亚洲日本丝袜连裤袜办公室| 亚洲一区二区三区精品在线| 日本中文字幕一区二区有限公司| 精品一区二区三区蜜桃| 不卡视频在线看| 欧美亚男人的天堂| 精品久久久久久久久久久院品网| 国产精品视频看| 亚洲成av人影院在线观看网| 美女视频黄免费的久久| 成人av中文字幕| 欧美一区二区视频观看视频| 国产农村妇女精品| 午夜视频一区二区| 国产91高潮流白浆在线麻豆| 欧美午夜精品一区二区蜜桃| 精品福利视频一区二区三区| 亚洲天堂2014| 国产综合久久久久影院| 色噜噜狠狠一区二区三区果冻| 91精品久久久久久久久99蜜臂| 欧美激情综合五月色丁香小说| 国产欧美一区二区精品秋霞影院| 一区二区三区91| 国产专区综合网| 欧美性大战久久久| 国产午夜精品一区二区 | 国产一区二区在线观看免费 | 欧美国产国产综合| 日日夜夜精品视频免费| 91美女片黄在线观看91美女| 国产精品一区二区免费不卡| 在线观看一区二区视频| 久久九九99视频| 亚洲一区在线观看免费观看电影高清| 韩国av一区二区三区在线观看 | 国产精品国产成人国产三级| 偷拍一区二区三区四区| caoporm超碰国产精品| 日韩精品一区二区三区视频播放| 日韩美女视频一区二区| 国产一区二区伦理片| 欧美三级电影精品| 日韩美女精品在线| 国产成人免费在线视频| 日韩一区二区三区免费看 | 国产精品护士白丝一区av| 美女视频黄a大片欧美| 欧美午夜不卡在线观看免费| 国产拍欧美日韩视频二区| 美日韩一区二区| 7799精品视频| 亚洲午夜激情av| 色中色一区二区| 国产精品久线观看视频| 韩国视频一区二区| 欧美一区二区在线免费观看| 一区二区三区视频在线看| 成人aa视频在线观看| 26uuu精品一区二区| 免费观看在线色综合| 欧美日韩mp4| 亚洲高清免费一级二级三级| 在线亚洲人成电影网站色www| 国产精品美女久久久久久2018| 国产精品自产自拍| 久久欧美一区二区| 久久成人免费电影| 日韩美女在线视频| 日韩电影免费一区| 这里是久久伊人| 欧美aaa在线| 欧美v日韩v国产v| 久久爱www久久做| 欧美刺激脚交jootjob| 黄色成人免费在线| 精品国产一区二区亚洲人成毛片| 久久99热这里只有精品| 欧美成人video| 国内精品免费在线观看| 国产亚洲午夜高清国产拍精品| 国产在线精品一区二区夜色 | 国产精品久久久久久久久免费樱桃| 国产精品亚洲а∨天堂免在线| 久久久国产精品午夜一区ai换脸| 狠狠色丁香久久婷婷综合丁香| ww久久中文字幕| 丰满亚洲少妇av| 亚洲精品水蜜桃| 在线成人av网站| 精品一区精品二区高清| 国产日韩亚洲欧美综合| 9久草视频在线视频精品| 一区二区在线电影| 91精品视频网| 国产精品综合二区| 亚洲视频免费在线观看| 欧美影视一区在线| 美女国产一区二区| 欧美激情一区二区三区在线| 91麻豆精东视频| 日韩电影在线观看网站| 久久久精品黄色| 日本高清视频一区二区| 奇米一区二区三区| 亚洲国产精品精华液ab| 在线日韩一区二区| 国产自产2019最新不卡| 亚洲人成伊人成综合网小说| 欧美日韩色一区| 国产在线播放一区| 夜夜爽夜夜爽精品视频| 日韩免费看网站| 91麻豆精品在线观看| 六月丁香综合在线视频| 亚洲婷婷国产精品电影人久久| 91麻豆精品国产91| 丁香天五香天堂综合| 亚洲永久免费视频| 久久在线观看免费| 欧美性极品少妇| 国产一区二区电影| 亚洲国产sm捆绑调教视频 | 亚洲激情自拍偷拍| 日韩精品中文字幕在线不卡尤物| 北条麻妃一区二区三区| 日韩电影在线一区二区三区| 国产精品久久久久久亚洲毛片 | 亚洲一区日韩精品中文字幕| 欧美va日韩va| 欧美三片在线视频观看| 国产精品99久久久久久久女警| 午夜国产精品一区| 国产精品久久久久7777按摩| 欧美猛男gaygay网站| www..com久久爱| 久热成人在线视频| 一区二区三区成人在线视频| 久久久久久久国产精品影院| 欧美精品一二三区| av在线免费不卡| 日本vs亚洲vs韩国一区三区二区| 国产人成亚洲第一网站在线播放| 欧美军同video69gay| 99国产精品久久| 国产精品白丝jk白祙喷水网站| 国产成人免费在线视频| 亚洲第一搞黄网站| 中文字幕亚洲精品在线观看| 三级影片在线观看欧美日韩一区二区| 国产亚洲一区二区在线观看| 欧美成人女星排名| 欧美喷水一区二区| 欧美性感一区二区三区| 91免费版在线| 成人av在线电影| 国产老妇另类xxxxx| 久久成人久久鬼色| 日本大胆欧美人术艺术动态| 亚洲综合av网| 亚洲欧美日韩电影| 1024成人网色www| 中文字幕一区二区三区精华液| 日韩免费看的电影| 精品久久久久av影院| 欧美日韩激情在线| 欧美色图12p| 欧美性极品少妇| 欧美日韩国产综合草草|