編輯:關於Android編程
接口至少有兩個寄存器,即“通用IO控制寄存器”與“通用IO數據寄存器”。數據寄存器的各位都直接引到芯片外部,而對這種寄存器中每一位的作用,即每一位的信號流通方向,則可以通過控制寄存器中對應位獨立的加以設置。這樣,有無GPIO接口也就成為微控制器區別於微處理器的一個特征。
static int __init sun4i_gpio_init(void) {
int err;
int i;
int sun4i_gpio_used = 0;
struct sun4i_gpio_data *gpio_i;
/*
include /linux/sysfs.h
-------------------------------------
struct attribute {
const char *name;
struct module *owner;
mode_t mode;
};
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
};
這2個都是sys文件系統的中的結構體,關鍵點在device_attribute 中的show 和 store,其實就是對設備的讀和寫
*/
struct device_attribute *attr_i;
char pin[16];
pr_info("sun4i gpio driver init\n");
/*
用來獲取sys_config1.fex主鍵gpio_para中的子鍵gpio_used的值,如果gpio_used的值為0,則表示該驅動已經通過配置關閉了,這樣就是實現了用配置來控制打開和關閉驅動
這裡我們知道了如果我們要增加單獨控制的gpio,我們只需要在sys_config1.fex文件中,添加gpio_para的主鍵和名為gpio_used的子鍵
*/
err = script_parser_fetch("gpio_para", "gpio_used", &sun4i_gpio_used, sizeof(sun4i_gpio_used)/sizeof(int));
if(err) {
pr_err("%s script_parser_fetch \"gpio_para\" \"gpio_used\" error\n", __FUNCTION__);
goto exit;
}
if(!sun4i_gpio_used) {
pr_err("%s sun4i_gpio is not used in config\n", __FUNCTION__);
err = -1;
goto exit;
}
/*
用來獲取sys_config1.fex主鍵gpio_para中的子鍵gpio_num的值,很顯然子鍵gpio_num的值,用來定義配置中一共有多少個gpio
*/
err = script_parser_fetch("gpio_para", "gpio_num", &sun4i_gpio_num, sizeof(sun4i_gpio_num)/sizeof(int));
if(err) {
pr_err("%s script_parser_fetch \"gpio_para\" \"gpio_num\" error\n", __FUNCTION__);
goto exit;
}
sun4i_gpio_dbg("sun4i_gpio_num:%d\n", sun4i_gpio_num);
if(!sun4i_gpio_num) {
pr_err("%s sun4i_gpio_num is none\n", __FUNCTION__);
err = -1;
goto exit;
}
/*
注冊一個雜項設備,主設備號是10,此設備號由系統來定義
*/
err = misc_register(&sun4i_gpio_dev);
if(err) {
pr_err("%s register sun4i_gpio as misc device error\n", __FUNCTION__);
goto exit;
}
/*
根據gpio的個數,對每個gpio結構體申請一塊內存,用來保存從sys_config1.fex文件中讀取到的每個gpio的屬性
*/
psun4i_gpio = kzalloc(sizeof(struct sun4i_gpio_data) * sun4i_gpio_num, GFP_KERNEL);
/*
按照gpio的個數,對每個gpio申請一個設備屬性,每個設備屬性將用來對sys文件系統中的gpio的讀寫
*/
pattr = kzalloc(sizeof(struct device_attribute) * sun4i_gpio_num, GFP_KERNEL);
if(!psun4i_gpio || !pattr) {
pr_err("%s kzalloc failed\n", __FUNCTION__);
err = -ENOMEM;
goto exit;
}
gpio_i = psun4i_gpio;
attr_i = pattr;
/*
循環對每個gpio的在sys_config1.fex文件的值進行讀取,並將解析出來的值保存到gpio_i中
*/
for(i = 0; i < sun4i_gpio_num; i++) {
/*
由此可以看出,子鍵類似於gpio_pin_1 gpio_pin_2 gpio_pin_3 ......這種方式來命名的
*/
sprintf(pin, "gpio_pin_%d", i+1);
sun4i_gpio_dbg("pin:%s\n", pin);
err = script_parser_fetch("gpio_para", pin,
(int *)&gpio_i->info, sizeof(script_gpio_set_t));
if(err) {
pr_err("%s script_parser_fetch \"gpio_para\" \"%s\" error\n", __FUNCTION__, pin);
break;
}
/*
************************************************************************************************************
* 這是 CSP_GPIO_Request_EX函數的說明
* CSP_GPIO_Request_EX
*
* 函數名稱:
*
* 參數說明: main_name 傳進的主鍵名稱,匹配模塊(驅動名稱)
*
* sub_name 傳進的子鍵名稱,如果是空,表示全部,否則尋找到匹配的單獨GPIO
*
* 返回值 :0 : err
* other: success
*
* 說明 :暫時沒有做沖突檢查
*
*
************************************************************************************************************
*/
gpio_i->gpio_handler = gpio_request_ex("gpio_para", pin);
sun4i_gpio_dbg("gpio handler: %d", gpio_i->gpio_handler);
if(!gpio_i->gpio_handler) {
pr_err("%s can not get \"gpio_para\" \"%s\" gpio handler,\
already used by others?", __FUNCTION__, pin);
break;
}
sun4i_gpio_dbg("%s: port:%d, portnum:%d\n", pin, gpio_i->info.port,
gpio_i->info.port_num);
/* Turn the name to pa1, pb2 etc... */
sprintf(gpio_i->name, "p%c%d", 'a'+gpio_i->info.port-1, gpio_i->info.port_num);
sun4i_gpio_dbg("psun4i_gpio->name%s\n", gpio_i->name);
/* Add attributes to the group */
/*
這裡將屬性初始化到sys文件系統,並對device_attribute 結構體的成員賦值,這樣其實就是定義了讀寫IO的函數
sun4i_gpio_enable_show就是讀出IO的data,而sun4i_gpio_enable_store就是往IO中寫入值
*/
sysfs_attr_init(&attr_i->attr);
attr_i->attr.name = gpio_i->name;
attr_i->attr.mode = S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH;
attr_i->show = sun4i_gpio_enable_show;
attr_i->store = sun4i_gpio_enable_store;
sun4i_gpio_attributes[i] = &attr_i->attr;
gpio_i++;
attr_i++;
}
sysfs_create_group(&sun4i_gpio_dev.this_device->kobj,
&sun4i_gpio_attribute_group);
exit:
return err;
}
static void __exit sun4i_gpio_exit(void) {
sun4i_gpio_dbg("bye, sun4i_gpio exit\n");
sysfs_remove_group(&sun4i_gpio_dev.this_device->kobj,
&sun4i_gpio_attribute_group);
misc_deregister(&sun4i_gpio_dev);
kfree(psun4i_gpio);
kfree(pattr);
}
struct sun4i_gpio_data,這個結構體其實就用來描述一個gpio
struct sun4i_gpio_data {
int status; //當前狀態,其實就是gpio的值,0或者1
unsigned gpio_handler; //用來標識這個gpio,相當於一個唯一的id
script_gpio_set_t info;
char name[8]; //8個字節的字符串用來描述名字 例如"PI09"
}
script_gpio_set_t 結構體,才是真正用來描述單個的gpio
typedef struct
{
char gpio_name[32];
int port;
int port_num;
int mul_sel;
int pull;
int drv_level;
int data;
} script_gpio_set_t;


static int sun4i_gpio_open(struct inode *inode, struct file *file) {
pr_info("sun4i_gpio open\n");
return 0;
}
ssize_t sun4i_gpio_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) {
pr_info("sun4i_gpio write\n");
return 0;
}
static const struct file_operations sun4i_gpio_fops = {
.open = sun4i_gpio_open,
.write = sun4i_gpio_write,
.release = sun4i_gpio_release
};
Android使用PullToRefresh完成ListView下拉刷新和左滑刪除功能
ListView下刷新刷功能相信從事Android開發的猿友們並不陌生,包括現在Google親兒子SwipeRefreshLayout實現效果在一些APP上也能看見(不過
android筆記4——Fragment的使用
說明第一下:按照前面的方式我們創建了項目,如果使用的是最新的ADT,Minimum Android SDK選的是android2.*或1.*,此時會默認創建一個兼容的項目
Android源碼中的適配器模式
在Android開發過程中,ListView的Adapter是我們最常見的類型之一,我們需要使用Adapter加載Item View的布局,並且進行數據綁定、緩存復用等操
基於Android實現仿QQ5.0側滑
本課程將帶領大家通過自定義控件實現QQ5.0側滑菜單,課程將循序漸進,首先實現最普通的側滑菜單,然後引入屬性動畫與拖動菜單效果相結合,最終實現QQ5.0側滑菜單效果。通過