2015年3月5日 星期四

增加linux kernel的marco到eclipse上



參考自:
http://blog.csdn.net/blaider/article/details/7474786
http://jarson.asia/%E4%BD%BF%E7%94%A8eclipse%E5%BC%80%E5%8F%91linux%E9%A9%B1%E5%8A%A8/


1. 取得kernel的所有define值

1.1 切換到autoconf.h的目錄下:
  新一點的kernel:
  cd {path of kernel dir}/include/generated/
  舊一點的kernel:
  cd {path of kernel dir}/include/linux/
1.2 將autoconf.h 轉換輸出成 symbol.xml
  cat autoconf.h |grep define |awk '{print "" $2 "" $3 ""}' > symbol.xml


2. 建立eclipse設定初始值

新建一個project, 建完於其上右鍵選properties, 左側選 c/c++ general -> paths and symbols, 之後右側
2.1  includes/languages/GNU C 新增以下路徑:
  {path of kernel dir}/include
  {path of kernel dir}/arch/arm/include (x86的話改成:{path of kernel dir}/arch/x86/include)
2.2 symbols/languages/GNU C 新增以下macro
  Name: __KERNEL__
  Value: 1
  (在之後輸出的.xml 中會是 "<macro><name>__KERNEL__</name><value>1</value></macro>")

3. 增加eclipse所需的define值

3.1 Export ProjNameSetting.xml
  File->gt;Export(C/C++/C/C++ Project Settings) 輸出成 ProjNameSetting.xml
3.2 增加autoconf.h中的define值
  在 <macro><name>__KERNEL__</name><value>1</value></macro> 後增加 1.2中 symbol.xml的所有內容

4. Import ProjNameSetting.xml

  File->Import(C/C++/C/C++ Project Settings) 選擇 Step3 中的ProjNameSetting.xml


5. Refresh

在project 上,右鍵選Indexer->Rebuild


//之後再補上在其上編譯driver的點

2014年3月4日 星期二

Demo project

This is a simple project for demonstration.
To check the followings for more detail.



1. Video:
             


2. Operation flow chart:



3. Connection between the device and the application on PC:
                                       





2011年12月16日 星期五

在Vista下安裝VC6及其sp6


//VC6的安裝
1. 以系統管理員權限執行: 按右鍵選"系統管理員權限執行"執行安裝檔。
2. 安裝時選"自訂安裝(Custom setup)"。
3. 在"自訂安裝(Custom setup)"細項中選"Tools",
按下右側的"change option",進入後,將"OLE/COM object viewer"的勾選移除。
4. 之後便能順利完成安裝。


//VC6 sp6的安裝
只要VC6順利完成安裝,sp6也能順利完成。
唯一要注意的是語系問題,安裝英文版的VC6只能用英文版的sp6來進行更新。

1. 以系統管理員權限執行: 按右鍵選"系統管理員權限執行"執行安裝檔


參考自:
http://social.msdn.microsoft.com/Forums/eu/windowsgeneraldevelopmentissues/thread/20336266-67e0-4ee0-baec-5225bc07b06d

2011年6月10日 星期五

二進位正負表示


-2的表示法:


Step 1:
找出+2的表示法: 0000 0010

Step 2:
invert all bits.
0000 0010 -> 1111 1101

Step 3:
加上1.
1111 1101 + 1 = 1111 1110

1111 1110 即為 -2 的表示法。






(+2) + (-2) = 0:


0000 0010 + 1111 1110 = 1 0000 0000

0000 0010
+ 1111 1110
---------------
1 0000 0000

bit 0-bit 7 為 0000 0000
bit 8 進位為 1

只看bit0-bit7
所以 0000 0000 = 0






1111 1110 代表十進位數值為何?

Step 1:
1111 1110 -1 = 1111 1101

Step 2:
invert all bits.
1111 1101 -> 0000 0010 -> 2










2009年9月18日 星期五

[WIA]Item Tree





***************************************************************************

1. Item Tree 架構, 如圖1
1.1 有一個Root item 及一個 Flatbed or Feeder item(Flatbed 和 Feeder 共用一個Item)
1.2 每一個item 中有許多WINDOWS 定義好的property (DIP_xxx_xxx, DPA_xxx_xxx, ...)
1.3 0000\xxx 或 0001\xxx 為 WINDOWS 決定的。


2. 可以使用wiatest.exe 看到Item Tree 中的每個Item 及其所有的property, 如圖2
3. Item Tree 由AP, Wia service , mini driver 各擁有一份。wia service 會自行同步這三份。



圖1:



圖2:







建立時機點:


//
//建立Item 的架構
//
IWiaMiniDrv::drvInitializeWia(...)
{
.
.
//建立Root Item
IWiaDrvItem *pIWiaDrvRootItem = NULL;
wiasCreateDrvItem(... , &pIWiaDrvRootItem)
.
.
//建立Flatbed Item
IWiaDrvItem *pIWiaDrvNewItem = NULL;
wiasCreateDrvItem(... , &pIWiaDrvNewItem)

//attach Flatbed Item to Root Item
pIWiaDrvNewItem->AddItemToFolder(pIWiaDrvRootItem);
.
.
.

}


//
//建立每個Item 中的property 及其初始值, 一個Item 會進來一次(Root 一次, Flatbed 一次)
//
IWiaMiniDrv::drvInitItemProperties(...)
{
//判斷進來的是Root 或 Flatbed 寫入相對映的property(使用wiasXXX 的function)
//ex:
//wiasSetItemPropNames();
//wiasWriteMultiple();
//wiasSetItemPropAttribs();
//.
//.
.
.
.
}




p.s.
在Vista/7 下,其Item Tree架構差不多,如下:

1. Item Tree 架構,
1.1 有一個Root item 及一個 Flatbed or Feeder item or 其它的 Item(Flatbed 和 Feeder 各自有其Item)
1.2 每一個item 中有許多WINDOWS 定義好的property (DIP_xxx_xxx, DPA_xxx_xxx, ...), 但有些property 的名稱改變,如

(DPA_xxx_xx -> DPS_xxx_xxx), 而且可能會有所移動(ex: 從 Root -> Flatbed)

2. 可以使用wiainfo2.exe 看到Item Tree 中的每個Item 及其所有的property
3. Item Tree 由AP, Wia service , mini driver 各擁有一份。wia service 會自行同步這三份。

2009年9月10日 星期四

[WIA] the order of Release

CWiaDevice::CWiaDevice

HRESULT CWIADriver::drvInitializeWia(__inout BYTE *pWiasContext,
LONG lFlags,
__in BSTR bstrDeviceID,
__in BSTR bstrRootFullItemName,
__in IUnknown *pStiDevice,
__in IUnknown *pIUnknownOuter,
__out IWiaDrvItem **ppIDrvItemRoot,
__out IUnknown **ppIUnknownInner,
__out LONG *plDevErrVal)





HRESULT CWIADriver::drvUnInitializeWia(__inout BYTE *pWiasContext)

CWiaDevice::~CWiaDevice


//
Wia UI 出現時一定會呼叫drvInitializeWia,
但drvInitializeWia 和 drvUnInitializeWia 並不一定會成對出現。所以有可能呼叫多次的drvInitializeWia, 而只呼叫一次的drvUnInitializeWia.

drvInitializeWia: 只在第一次呼叫時初始化所需資源。之後只要回傳ok.
drvUnInitializeWia:
CWiaDevice::~CWiaDevice:
1. 釋放資源
2. CancelIO(SetNotificationHandle(NULL))
3. Release handle(CreateFile 建立用來控制device)





定義:
******************************************************************************
一個 Hanlde週期(Handle life cycle):
1. device 插入到拔出
2. 開機到關機


WIA UI:
default WIA AP(offered by WINDOWS)


class CWIADriver : public INonDelegatingUnknown, // NonDelegatingUnknown
public IStiUSD, // STI USD interface
public IWiaMiniDrv // WIA Minidriver interface
CWIADriver :
component 內的一個 class 用來提供 IStiUSD, IWiaMiniDrv兩個 Interface


說明:
******************************************************************************
IStiUSD::Initialize():
週期時機:週期開始
呼叫時機:一偵測到Device 的存在--安裝完Driver或插入Device(device 插入或開機)
應作動作:初始化 Handle(created by CreateFile)

IWiaMiniDrv::drvInitializeWia:
週期時機:週期內
呼叫時機:建立連線(IWiaDevMgr::CreateDevice), ex: 打開WIA UI
應作動作:
1. 在第一次進來,保存傳入的IStiDevice 指標(IStiDevice 為 IStiUSD的使用者介面),
下次再進來時便以此指標是否已有值來判斷是否為一個週期的開始,
指標內有值便為週期內,否則為一新的週期。
2. 增加連線計數(進來一次加一)

IWiaMiniDrv::drvUnInitializeWia:
週期時機:週期內
呼叫時機:結束連線
應作動作:
1. 減少連線計數(進來一次減一)
如果連線計數為0 時釋放掉一些週期內可以釋放的large memory


CWiaDevice::~CWiaDevice:
週期時機:週期結束
呼叫時機:一偵測到Device 的'不'存在(device 拔出或關機)
應作動作:
1. 釋放 Handle(created by CreateFile),
如果有支援push mode 得先CancelIO(by SetNotificationHandle(NULL))


WDK 中說明:
1. 並不保證每一次的IWiaMiniDrv::drvInitializeWia 和 IWiaMiniDrv::drvUnInitializeWia 會成對出現。
2. 週期內,不保證每一次(除了第一次)都會先呼叫IWiaMiniDrv::drvInitializeWia
再呼叫其它 IWiaMiniDrv的function.

2009年8月31日 星期一

指標的指標使用的兩種時機

1. function
真正的記憶體在function 內被allocate, caller 只要有一個指標,傳入指標的位址(即指標的指標)即可使用。
只是使用完畢得由caller release 記憶體。

#define MEM_SIZE 100


//function code:
Func(BYTE **pMem)
{
*pMem= malloc(100);
}

//caller code:
Main()
{
BYTE *pBuf=NULL;


Func(&pBuf);

//
//do something with "pBuf"
//
.
.
.

//
//Release mem
//
Free(pBuf);
}


2. 指標的陣列:
等同是create 一個指標的陣列
Method1: by Array
Method2: by pointer


#define METHOD_ARRAY


Main()
{
int **pArray=NULL;
int pIntArray[3];
int i;

pArray = (int **)malloc(3*sizeof(int*));

//assign address
for (i=0; i<3; i++)
{
#ifdef METHOD_ARRAY
//
// by Array
//
pArray[i] = &(pIntArray[i]);
#else
//
// by pointer
//
*(pArray+i)= &(pIntArray[i]);
#endif

}

//show
for (i=0; i<3; i++)
{
#ifdef METHOD_ARRAY
//
// by Array
//
printf("%d\n", *(ppValue[i]));
#else
//
// by pointer
//
printf("%d\n", *((int *)*(ppValue+i)));
#endif
}

free(pArray);

}