Android下led控制(下)--Linux驅動部分--script與gpio(全志)
前面寫了三篇關於全志CQA83T下Android控制led的博文,但是還是有很多東西可以學習,可以寫寫作為學習記錄。如果看原始碼,繞不過script這個東西,這個不是像其他系統指令碼一樣,這裡的script應該是全志自己加上去的,不是原生系統的內容(暫時給感覺是這樣)。這一篇還是要藉助led驅動的原始碼來引入,下面再貼一下led.c的原始碼:
#include <linux/types.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/init.h> #include <linux/input.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/jiffies.h> #include <linux/module.h> #include <linux/gpio.h> #include <linux/input/matrix_keypad.h> #include <linux/slab.h> #include <asm/io.h> #include <mach/irqs.h> #include <mach/hardware.h> #include <mach/sys_config.h> #include <linux/miscdevice.h> #include <linux/printk.h> #include <linux/kernel.h> #define LED_IOCTL_SET_ON 1 #define LED_IOCTL_SET_OFF 0 static script_item_u led_val[5]; static script_item_value_type_e led_type; static struct semaphore lock; static int led_open(struct inode *inode, struct file *file) { if (!down_trylock(&lock)) return 0; else return -EBUSY; } static int led_close(struct inode *inode, struct file *file) { up(&lock); return 0; } static long led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { unsigned int n; n = (unsigned int)arg; switch (cmd) { case LED_IOCTL_SET_ON: if (n < 1) return -EINVAL; if(led_val[n-1].gpio.gpio != -1) { __gpio_set_value(led_val[n-1].gpio.gpio, 1); printk("led%d on !\n", n); } break; case LED_IOCTL_SET_OFF: default: if (n < 1) return -EINVAL; if(led_val[n-1].gpio.gpio != -1) { __gpio_set_value(led_val[n-1].gpio.gpio, 0); printk("led%d off !\n", n); } break; } return 0; } static int __devinit led_gpio(void) { int i = 0; char gpio_num[10]; for(i =1 ; i < 6; i++) { sprintf(gpio_num, "led_gpio%d", i); led_type= <span style="color:#ff0000;background-color: rgb(102, 255, 153);">script_get_item</span>("led_para", gpio_num, &led_val[i-1]); if(SCIRPT_ITEM_VALUE_TYPE_PIO != led_type) { printk("led_gpio type fail !"); // gpio_free(led_val[i-1].gpio.gpio); led_val[i-1].gpio.gpio = -1; continue; } if(0 != gpio_request(led_val[i-1].gpio.gpio, NULL)) { printk("led_gpio gpio_request fail !"); led_val[i-1].gpio.gpio = -1; continue; } if (0 != gpio_direction_output(led_val[i-1].gpio.gpio, 0)) { printk("led_gpio gpio_direction_output fail !"); // gpio_free(led_val[i-1].gpio.gpio); led_val[i-1].gpio.gpio = -1; continue; } } return 0; } static struct file_operations leds_ops = { .owner = THIS_MODULE, .open = led_open, .release = led_close, .unlocked_ioctl = led_ioctl, }; static struct miscdevice leds_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "led", .fops = &leds_ops, }; static int __devexit led_remove(struct platform_device *pdev) { return 0; } static int __devinit led_probe(struct platform_device *pdev) { int led_used; script_item_u val; script_item_value_type_e type; int err; printk("led_para!\n"); type = <span style="color:#ff0000;background-color: rgb(102, 255, 153);">script_get_item</span>("led_para", "led_used", &val); if (SCIRPT_ITEM_VALUE_TYPE_INT != type) { printk("%s script_get_item \"led_para\" led_used = %d\n", __FUNCTION__, val.val); return -1; } led_used = val.val; printk("%s script_get_item \"led_para\" led_used = %d\n", __FUNCTION__, val.val); if(!led_used) { printk("%s led_used is not used in config, led_used=%d\n", __FUNCTION__,led_used); return -1; } err = led_gpio(); if (err) return -1; sema_init(&lock, 1); err = misc_register(&leds_dev); printk("======= cqa83 led initialized ================\n"); return err; } struct platform_device led_device = { .name = "led", }; static struct platform_driver led_driver = { .probe = led_probe, .remove = __devexit_p(led_remove), .driver = { .name = "led", .owner = THIS_MODULE, }, }; static int __init led_init(void) { if (platform_device_register(&led_device)) { printk("%s: register gpio device failed\n", __func__); } if (platform_driver_register(&led_driver)) { printk("%s: register gpio driver failed\n", __func__); } return 0; } static void __exit led_exit(void) { platform_driver_unregister(&led_driver); } module_init(led_init); module_exit(led_exit); MODULE_DESCRIPTION("Led Driver"); MODULE_LICENSE("GPL v2");
看上面標註的地方(紅字綠底),這裡引用了一個script_get_item函式,我們可以檢視全志的資料可以知道這個函式功能是獲取配置指令碼中某一項子健。通過該說明文件,我們可以知道Script這個功能裡的函式是為了解析系統管腳配置指令碼sys_config.fex中的內容。
通俗來說吧,就是開發板的管腳配置會寫在一個叫sys_config.fex的檔案中,而script的功能就是去讀這個檔案並進行解析儲存,在程式使用某個管腳時去從這些儲存的內容中查詢,如果能夠查詢到並且可用,即是匹配成功,那麼程式才能使用該管腳。Script這個內容在三個檔案中,sys_config.fex,sys_config.h,sys_config.c。sys_config.fex就是系統管腳配置檔案,sys_config.h宣告標頭檔案和資料結構,sys_config.c實現了介面函式。由於sys_config.fex內容比較多,這裡就不全部顯示了,現在說led驅動,就只貼出來led的配置內容。其檔案在lichee\tools\pack\chips\sun8iw6p1\configs\f1\sys_config.fex
簡單解釋一下這幾項,裡面的led_used和下面幾個led_gpioN(N可以是1、2、3、4、5)稱為子健。後面的值是這樣的格式:;---------------------------------------------------------------------------------- ;led ;---------------------------------------------------------------------------------- [led_para]<span style="white-space:pre"> </span>//主鍵 led_used = 1<span style="white-space:pre"> </span>//使用使能,0不能使用,1能使用 led_gpio1 = port:PL09<1><default><default><1><span style="white-space:pre"> </span> led_gpio2 = port:PL10<1><default><default><1> led_gpio3 = port:PH04<1><default><default><1> led_gpio4 = port:PH09<1><default><default><1> led_gpio5 = port:PC07<1><default><default><1>
port:<port><mux feature><pullup/down><drive capability><output level>
每一項的意義:
<port>:要設定的io口(例如PL09)
<mux feature>:io口功能配置:0是input,1是output,2到7可以看板子的具體配置
<pullup/down>:0是disable;1是pullup enable;2是pulldown enable。但是這個配置只要引腳被配置成輸入才是有效的。
<drive capability>:驅動能力配置,驅動能力預設是毫安(mA)級別的,配置成0到3對應,10mA,20mA,30mA,40mA。
<output level>:設定初始化時的電平輸出值,配置為0是低電平,配置為1是高電平。但是隻有引腳被配置為輸出時才是有有效的。
其中<pullup/down>,<drive capability>,<output level>三個的值可以配置為default,設定為default是和上次保持不變。
這些內容可以在http://linux-sunxi.org/Fex_Guide#FEX_Description這個網站上看到。
下面來看一下,script_get_item這個函式,這個函式的實現在linux-3.4\arch\arm\mach-sunxi\sys_config.c
<span style="color:#ff0000;">script_item_value_type_e</span>
script_get_item(char *main_key, char *sub_key, script_item_u *item)
{
int main_hash, sub_hash;
<span style="color:#009900;">script_main_key_t *mainkey = g_script;</span>
if(!main_key || !sub_key || !item || !g_script) {
return SCIRPT_ITEM_VALUE_TYPE_INVALID;
}
main_hash = hash(main_key);
sub_hash = hash(sub_key);
/* try to look for the main key from main key list */
while(mainkey) {
if((mainkey->hash == main_hash) && !strcmp(mainkey->name, main_key)) {
/* find the main key */
script_sub_key_t *subkey = mainkey->subkey;
while(subkey) {
if((subkey->hash == sub_hash) && !strcmp(subkey->name, sub_key)) {
/* find the sub key */
*item = *subkey->value;
return <span style="color:#ff0000;">subkey->type</span>;
}
subkey = subkey->next;
}
/* no sub key defined under the main key */
return SCIRPT_ITEM_VALUE_TYPE_INVALID;
}
mainkey = mainkey->next;
}
return SCIRPT_ITEM_VALUE_TYPE_INVALID;
}
EXPORT_SYMBOL(script_get_item);
這個函式的作用是返回的是子健的type,我們來看一下子健的定義型別:
/*
* define script item management data
* @name: item name, which is defined left of '='
* @value: value of the item
* @type: type of the item, interge / string / gpio?
* @hash: hash value of sub key name, for searching quickly
* @next: pointer for list
*/
typedef struct {
char name[SCRIPT_NAME_SIZE_MAX];
script_item_u *value;
script_item_value_type_e type;
int hash;
void *next;
} script_sub_key_t;
這個一個子健的資料結構體,包括名稱,值,模式,雜湊碼,下一個節點指標。再看一下type的定義:
/*
* define types of script item
* @SCIRPT_ITEM_VALUE_TYPE_INVALID: invalid item type
* @SCIRPT_ITEM_VALUE_TYPE_INT: integer item type
* @SCIRPT_ITEM_VALUE_TYPE_STR: strint item type
* @SCIRPT_ITEM_VALUE_TYPE_PIO: gpio item type
*/
typedef enum {
SCIRPT_ITEM_VALUE_TYPE_INVALID = 0,
SCIRPT_ITEM_VALUE_TYPE_INT,
SCIRPT_ITEM_VALUE_TYPE_STR,
SCIRPT_ITEM_VALUE_TYPE_PIO,
} script_item_value_type_e;
這是一個列舉資料型別,裡面包含了IO口的型別。我們知道這個函式是來查詢子健的型別type的,那麼是怎麼查詢的呢?先獲取主鍵的雜湊碼,然後再主鍵的列表中查詢雜湊碼和主鍵名稱,只有兩者都能夠匹配才繼續去查詢它下面的子健如果子健的雜湊碼和子健的名稱都匹配則返回自己的型別type。這裡說一下, 這裡的主鍵和子健是和上面看的sys_config.fex裡對應的。
現在我們知道怎查的了,但是儲存主鍵資訊和子健資訊的連結串列是怎麼來的呢?我們看上面程式碼裡面綠色的那一行,一切的對比資料都來自g_script這個量g_script。現在可以推斷,這個量裡面儲存了板子的管腳分配資訊並且是和sys_config.fex相對應的。我們再本函式裡面找這個變數,可以找到其定義:
static script_main_key_t *g_script;
這個是script_main_key_t型別的指標。繼續尋找這個,我們可以在這個資料夾下的 __init script_init(void)函式,在這個函式對變數g_script進行了初始化。
/*
* init script
*/
int __init script_init(void)
{
int i, j, count;
script_origin_head_t *script_hdr = __va(SYS_CONFIG_MEMBASE);
script_origin_main_key_t *origin_main;
script_origin_sub_key_t *origin_sub;
script_main_key_t *main_key;
script_sub_key_t *sub_key, *tmp_sub, swap_sub;
script_item_u *sub_val, *tmp_val, swap_val, *pval_temp;
if (cfg_addr > PHYS_OFFSET)
script_hdr = __va(cfg_addr);
printk("%s enter!\n", __func__);
if(!script_hdr) {
printk(KERN_ERR "script buffer is NULL!\n");
return -1;
}
/* alloc memory for main keys */
<span style="color:#ff0000;"> g_script = SCRIPT_MALLOC(script_hdr->main_cnt*sizeof(script_main_key_t));</span>
if(!g_script) {
printk(KERN_ERR "try to alloc memory for main keys!\n");
return -1;
}
origin_main = &script_hdr->main_key;
for(i=0; i<script_hdr->main_cnt; i++) {
<span style="color:#ff0000;"> main_key = &g_script[i];</span>
/* copy main key name */
strncpy(main_key->name, origin_main[i].name, SCRIPT_NAME_SIZE_MAX);
/* calculate hash value */
main_key->hash = hash(main_key->name);
if (origin_main[i].sub_cnt == 0) {
/* this mainkey have no subkey, skip subkey initialize */
main_key->subkey = NULL;
main_key->subkey_val = NULL;
count = 0;
goto next_mainkey;
}
/* allock memory for sub-keys */
main_key->subkey = SCRIPT_MALLOC(origin_main[i].sub_cnt*sizeof(script_sub_key_t));
main_key->subkey_val = SCRIPT_MALLOC(origin_main[i].sub_cnt*sizeof(script_item_u));
if(!main_key->subkey || !main_key->subkey_val) {
printk(KERN_ERR "try alloc memory for sub keys failed!\n");
goto err_out;
}
sub_key = main_key->subkey;
sub_val = main_key->subkey_val;
origin_sub = (script_origin_sub_key_t *)((unsigned int)script_hdr + (origin_main[i].offset<<2));
/* process sub keys */
for(j=0; j<origin_main[i].sub_cnt; j++) {
strncpy(sub_key[j].name, origin_sub[j].name, SCRIPT_NAME_SIZE_MAX);
sub_key[j].hash = hash(sub_key[j].name);
sub_key[j].type = (script_item_value_type_e)origin_sub[j].pattern.type;
sub_key[j].value = &sub_val[j];
if(origin_sub[j].pattern.type == SCIRPT_PARSER_VALUE_TYPE_SINGLE_WORD) {
sub_val[j].val = *(int *)((unsigned int)script_hdr + (origin_sub[j].offset<<2));
sub_key[j].type = SCIRPT_ITEM_VALUE_TYPE_INT;
} else if(origin_sub[j].pattern.type == SCIRPT_PARSER_VALUE_TYPE_STRING) {
sub_val[j].str = SCRIPT_MALLOC((origin_sub[j].pattern.cnt<<2) + 1);
memcpy(sub_val[j].str, (char *)((unsigned int)script_hdr + (origin_sub[j].offset<<2)), origin_sub[j].pattern.cnt<<2);
sub_key[j].type = SCIRPT_ITEM_VALUE_TYPE_STR;
} else if(origin_sub[j].pattern.type == SCIRPT_PARSER_VALUE_TYPE_GPIO_WORD) {
script_origin_gpio_t *origin_gpio = (script_origin_gpio_t *)((unsigned int)script_hdr + (origin_sub[j].offset<<2) - 32);
u32 gpio_tmp = port_to_index(origin_gpio->port, origin_gpio->port_num);
if(GPIO_INDEX_INVALID == gpio_tmp)
printk(KERN_ERR "%s:%s->%s gpio cfg invalid, please check sys_config.fex!\n",__func__,main_key->name,sub_key[j].name);
sub_val[j].gpio.gpio = gpio_tmp;
sub_val[j].gpio.mul_sel = (u32)origin_gpio->mul_sel;
sub_val[j].gpio.pull = (u32)origin_gpio->pull;
sub_val[j].gpio.drv_level = (u32)origin_gpio->drv_level;
sub_val[j].gpio.data = (u32)origin_gpio->data;
sub_key[j].type = SCIRPT_ITEM_VALUE_TYPE_PIO;
} else {
sub_key[j].type = SCIRPT_ITEM_VALUE_TYPE_INVALID;
}
}
/* process gpios */
tmp_sub = main_key->subkey;
tmp_val = main_key->subkey_val;
count = 0;
for(j=0; j<origin_main[i].sub_cnt; j++) {
if(sub_key[j].type == SCIRPT_ITEM_VALUE_TYPE_PIO) {
/* swap sub key */
swap_sub = *tmp_sub;
*tmp_sub = sub_key[j];
sub_key[j] = swap_sub;
/* swap sub key value ptr */
pval_temp = tmp_sub->value;
tmp_sub->value = sub_key[j].value;
sub_key[j].value = pval_temp;
/* swap key value */
swap_val = *tmp_val;
*tmp_val = main_key->subkey_val[j];
main_key->subkey_val[j] = swap_val;
tmp_sub++;
tmp_val++;
count++;
}
}
/* process sub key link */
for(j=0; j<origin_main[i].sub_cnt-1; j++) {
main_key->subkey[j].next = &main_key->subkey[j+1];
}
/* set gpio infermation */
next_mainkey:
main_key->gpio = main_key->subkey_val;
main_key->gpio_cnt = count;
<span style="color:#ff0000;">main_key->next = &g_script[i+1];</span>
}
g_script[script_hdr->main_cnt-1].next = 0;
/* dump all the item */
//script_dump_mainkey(NULL);
printk("%s exit!\n", __func__);
return 0;
err_out:
/* script init failed, release resource */
printk(KERN_ERR "init sys_config script failed!\n");
if(g_script) {
for(i=0; i<script_hdr->main_cnt; i++) {
main_key = &g_script[i];
origin_sub = (script_origin_sub_key_t *)((unsigned int)script_hdr + (origin_main[i].offset<<2));
if(main_key->subkey_val) {
for(j=0; j<origin_main[i].sub_cnt; j++) {
if(main_key->subkey[j].type == SCIRPT_ITEM_VALUE_TYPE_STR) {
if (main_key->subkey_val[j].str) {
SCRIPT_FREE(main_key->subkey_val[j].str, (origin_sub[j].pattern.cnt<<2) + 1);
}
}
}
SCRIPT_FREE(main_key->subkey_val, sizeof(script_item_u));
}
if(main_key->subkey) {
SCRIPT_FREE(main_key->subkey, sizeof(script_sub_key_t));
}
}
SCRIPT_FREE(g_script, script_hdr->main_cnt*sizeof(script_main_key_t));
g_script = 0;
}
return -1;
}
這個初始化過程有點複雜,簡單了說,就是下面這樣的
對g_script進行初始化之後,就能進行相應的查詢了。
如果仔細看led.c兩處呼叫的script_get_item,在led_probe函式裡呼叫是這樣的,
type = script_get_item("led_para", "<span style="color:#ff0000;">led_used</span>", &val);
而在led_gpio裡面呼叫是這樣的static int __devinit led_gpio(void)
{
int i = 0;
char gpio_num[10];
for(i =1 ; i < 6; i++) {
sprintf(gpio_num, "led_gpio%d", i);
led_type= script_get_item("led_para", <span style="color:#ff0000;">gpio_num</span>, &led_val[i-1]);
if(SCIRPT_ITEM_VALUE_TYPE_PIO != led_type) {
printk("led_gpio type fail !");
// gpio_free(led_val[i-1].gpio.gpio);
led_val[i-1].gpio.gpio = -1;
continue;
}
if(0 != gpio_request(led_val[i-1].gpio.gpio, NULL)) {
printk("led_gpio gpio_request fail !");
led_val[i-1].gpio.gpio = -1;
continue;
}
if (0 != gpio_direction_output(led_val[i-1].gpio.gpio, 0)) {
printk("led_gpio gpio_direction_output fail !");
// gpio_free(led_val[i-1].gpio.gpio);
led_val[i-1].gpio.gpio = -1;
continue;
}
}
return 0;
}
這倆有什麼不一樣,是子健不一樣,從前面的博文知道,led_probe函式是platform機制的探測函式,也是初始化函式,這裡先查led的子健led_used是否可用,然後再查具體gpio埠是否可用。也就是先查使能,如果使能則繼續查具體g皮哦埠能否可用。
這裡大概就是這麼多,簡單總結一下:在使用gpio驅動模型之前,先使用script查詢是否可用。
相關推薦
Android下led控制(下)--Linux驅動部分--script與gpio(全志)
前面寫了三篇關於全志CQA83T下Android控制led的博文,但是還是有很多東西可以學習,可以寫寫作為學習記錄。如果看原始碼,繞不過script這個東西,這個不是像其他系統指令碼一樣,這裡的script應該是全志自己加上去的,不是原生系統的內容(暫時給感覺是這樣)。這一
Android下led控制(中)--Linux部分
首先宣告一下我的實驗平臺,是全志CQA83T,成都啟劃資訊的板子。上面一篇部落格介紹了Android下led控制的Android部分。這一篇我想說說Linux下的部分,從上一篇我們可以知道,jni通過開啟led裝置/dev/led,進而使用ioctl函式來控制led的亮和滅
Android 充電LED控制
1、前言 充電LED燈控制是Android裝置的基本功能,主要用於提示裝置的電池狀態,充電狀態,滿電狀態,低電狀態,很多手機廠商還使用呼吸效果來顯示,普通的低端裝置會使用兩個LED燈表示,紅燈表示充電和低電,綠燈表示滿電。 之前寫的文章 《Android充電系統介紹》
linux驅動部分:交叉編譯驅動模組&模組驅動的相關操作&Makefile講解
根據下面的提醒,在自己電腦是的情況是:b1、模組整個操作流程 (1)載入模組:insmod globalfifo_zs_fzs.ko (2)檢視模組是否被載入:lsmod (3)檢視裝置號:cat /proc/devices (4)建立裝置節點:mknod /dev/
關於MAC下安裝virtual box linux 系統-主機與虛擬機器互通問題
在mac 下安裝了virtual box 虛擬機器 準備安裝 centos 系統 但是安裝完成後用橋接的方式無法進行 主機和虛擬機器之間的互ping 解決方法 1、關閉虛擬機器 2、修改虛擬機器配置 設定兩個網絡卡(網絡卡1用NAT、網絡卡2用“僅主機(Host-Only
Android 下led 的控制(上)--Android部分
首先說一下我的開發環境,硬體環境開發板使用的是全志的CQA83T板子,Android開發是windows下的eclipse。關於Android下控制led,主要有兩大部分,一是Android程式,二是Linux驅動開發。Android部分的開發肯定要使用Android nd
如何在Linux下模擬鍵盤輸入 利用驅動程式實現
參考:http://blog.csdn.net/absurd/archive/2009/09/13/4549514.aspx 驅動程式: #include <linux/module.h> #include <linux/modulepa
linux下寶塔控制面板怎麼解除安裝
你需要先在面板中將通過面板安裝的所有軟體解除安裝,如nginx、mysql、php 等等 然後,進入SSH命令列,輸入以下命令: /etc/init.d/bt stop && rm -f /etc/init.d/bt && rm -rf /www/server/pan
《5.linux驅動開發-第4部分-5.4.驅動框架入門之LED》
《5.linux驅動開發-第4部分-5.4.驅動框架入門之LED》 第一部分、章節目錄 5.4.1.何謂驅動框架 5.4.2.核心驅動框架中LED的基本情況 5.4.3.初步分析led驅動框架原始碼1 5.4.4.初步分析led驅動框架原始碼2 5.4.5.在核心中新增或去除某個驅動 5
Android——(高階控制元件下拉框與搜尋框)
1. 高階控制元件與低階控制元件區別 是否使用介面卡 2. 介面卡種類和作用 2.1 種類 陣列介面卡 ArrayAdapter new ArrayAdapt
Android自定義控制元件之仿汽車之家下拉重新整理
關於下拉重新整理的實現原理我在上篇文章Android自定義控制元件之仿美團下拉重新整理中已經詳細介紹過了,這篇文章主要介紹錶盤的動畫實現原理 汽車之家的下拉重新整理分為三個狀態: 第一個狀態為下拉重新整理狀態(pull to refresh),在這個狀
【Linux下許可權控制之chmod與chown命令】
chmod 用於配置檔案/目錄許可權 命名格式:chmod [選項] 檔案/目錄名 . 許可權類別: r 讀取 可用數字4表示 w 寫入 可用數字2表示 x 執行 可用數字1表示 . 歸屬類別: u 屬主 g 屬組 o 其它 a 所有人 . 操作符: + 給指定類別新增指定許可權(例如+x或a+x表
mongodb資料庫 linux下編譯mongodb的c++驅動
由於工作專案開發的需要 要使用mongodb資料庫 需要手動編譯mongo的c++庫,花費了大概兩天的時間,終於搞定,主要是上網搜資料。以下是本人收藏的幾篇部落格 https://mongodb.g
Linux下USB轉串列埠驅動
Linux發行版自帶usb to serial驅動,以模組方式編譯驅動,在核心原始碼目錄下執行Make MenuConfig選擇Devces drivers-->USB seupport--> <M>USB Serial Converter support --> <M
android 獲取指定路徑下所有檔案,將檔案從一個目錄copy到另一個目錄,執行linux命令
/** * 複製整個資料夾內容 ,可以從data/data/包名下 拷貝到 data/data/包名下。也可以copy到 /sdcard 下 * @param oldPath String 原檔案路徑 如:c:/fqf
Win7下安裝OK6410的USB驅動以及Linux下原始碼安裝dnw
因為飛凌的OK6410 的USB驅動在Win7下不能用,因此分享我的USB驅動的安裝過程。 一:Win7下的Ok6410 的USB下載線驅動安裝。 (參考文章:http://blog.sina.com.cn/s/blog_7f55cd3d01019sfq
Centos&Redhat下bcm43142博通無線網絡卡linux驅動之二
上次通過更換核心實現成功編譯驅動無線網絡卡,但是啟動到系統原核心下依然沒有bcm43142的驅動,遂準備在原核心下編譯驅動,記錄一下 ps:更推薦這種方法,避免因更換核心出現其他相容性問題 1.準備驅動包 hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz 點我下載
linux應用層下用C呼叫音訊驅動
static void audio_pause(void) { int err; if (alsa_can_pause) { if ((err = snd_pcm_pause(alsa_handler, 1)) < 0)
Android Camera HAL3中預覽preview模式下的控制流
本文均屬自己閱讀原始碼的點滴總結,轉賬請註明出處謝謝。歡迎和大家交流。qq:1037701636 email:Software:系統原始碼Android5.1Camera3研讀前沿: 當初在研讀Camera1.0相關的內容時,主要圍繞著CameraClient、CameraH
Linux下安裝NVIDIA顯示卡驅動(無集顯)
大部分Linux發行版都使用開源的顯示卡驅動nouveau,對於nvidia顯示卡來說,還是閉源的官方驅動的效果更好。最明顯的一點是,在使用SAC拾取震相的時候,使用官方顯示卡驅動在重新整理介面的時候要快很多。 對於CentOS使用者而言,有兩種安裝NVIDIA顯示卡驅