Sunday, April 17, 2011

USB and PIC Microprocessors 16C745 and 18F2455

http://www.alanmacek.com/usb/

Introduction

This page describes a project a colleague and I completed between September, 2000 and March, 2001 as part of the Engineering Physics degree program at the University of British Columbia.   In summary this project involved building a USB device using the PIC 16C745 microprocessor from Microchip.  The USB device consisted of a microphone, the microprocessor and other hardware and the device sent audio data to the host computer.
This page contains notes, links and code extracts from this project relating to USB, USB Human Interface Devices, the 16C745 microprocessor, and specifics of this project.  Hopefully this information will be helpful to your project.

Table of Contents


Result

We achieved our goal and built a working device.  This involved building the device hardware (microprocessor, microphone, and supporting electronics) and software (microprocessor code and host computer code).  Unfortunately, the relatively low sampling rate by the microprocessor in the analog-to-digital conversion process mangled the audio signal to make it indecipherable at the host computer, but loud/soft transitions were easily detected.
To top.

USB

USB (Universal Serial Bus) is a protocol that allows two way communication between peripheral devices and a host computer.  It is hot pluggable, allowing the device to be connected and/or removed while the computer is running.  There are lots of other features of USB.
The specifications for USB are available at www.usb.org.  Be warned that while this information is very thorough, it is not very practical for developing a device or software.  Technical documents are available at www.usb.org/developers/docs.html.
Here is a quick overview of what is involved in USB.
  • The Hardware:
    • A USB cable has four wires: power, ground, D+ and D-. The signal wires usually operate in differential mode (one is high while the other is low).
    • There are two types of USB devices: high speed and low speed. There are differences in the type, length and connectors that can be used with the two types. Generally the requirements are stricter for high speed devices. A high speed device can transfer data at a maximum of 12 Mbs while low speed is limited to 1.5 Mbs.  The PIC 16C745 can only operate at low speed standard.
    • The connector at the computer (A End) is a flattened rectangle while at the device (B end) the connector is square with two cut-off corners (necessary to be compliant with the high-speed standard but optional for low speed devices).
    • Each USB device is able to draw 100mA from the cable which allows a device to be bus powered. A device can negoiate up to 500mA once connected to the USB cable but this power may not be available.  If the power is unavailable the device must stay in a low power setting. Obviously devices can be powered externally as well.
  • The Software:
    • When a device is connected, the computer (or a hub) detects the device by a pullup resister (see circuit). A pullup resister on the D- wire signals a low speed device, while a high speed device has a pullup on the D+ wire. When detected a series of enumeration steps are started.
    • The enumeration process assigns an identifier number to the device (there can be a maximum of 127 devices on a network) and also tells the host computer what sort of capabilities a device has (input, ouput, etc). The device also informs the computer of its name (Vendor, Product, Version and Serial Number).
    • If the device identifies itself as a HID (Human Interface Device) then the device describes how the data should be interpreted. See the section on HID.
To top.

USB and Human Interface Devices (HID)

Human Interface Devices (HID) are a class of USB devices that give structure to the data that will transfered between the device and the host computer. During the enumeration process, the device describes the information that it can receive and send.  This allows a host computer to handle the data being received from the USB device without requiring a specially designed device driver.
The HID class is supposed to include devices such as a mouse, joystick, keyboard, etc. Because the host computer knows what the data means a device driver is not necessary for HID devices, the operating system can supply a generic HID driver. For instance, if you plug in a USB Mouse, it will immediately work because the OS knows how to interpret information received from a mouse.
Information on the HID class can be found at www.usb.org/developers/hidpage. You can see examples of HID descriptors starting on page 89 of the HID 1.1 spec from usb.org.

A very useful tool for designing HID class devices is the HID Descriptor Tool also available from usb.org. This tool allows you to put together the HID description and run it through the HID parser.

Some other useful tools are available from Intel University Press[1]. They include 'USB Single Step', 'USBView', 'HIDView' and the HID Descriptor Tool described above.

If you are using Visual C++, then the 'hview' sample program that comes with the Windows DDK is good for examining the HID descriptor and values. Unfortunately the program is more complicated than it needs to be and is not a good example of using the USB functions.
To top.

PIC 16C745

I used the PIC 16C745 from Microchip as the USB interface microcontroller. This chip belongs to a two chip family (along with the 16C765) called the 16c7xx.

The 16C745 is a 28 pin microprocessor operating at 24 Mhz. It has 8K of program memory, 256 bytes of RAM and 5 x 8bit analog inputs (the 16C765 has 40 pins and 8 analog inputs). The specifications are available from Microchip. The reference manual for the mid-range microprocessors is also useful.

Download the development environment from Microchip called MPLAB (freely available from Microchip's web site). Another necessary component is the USB firmware. The support files that I used seem to no longer exist on the Microchip web site being replaced by a more sophisticated USB example. The firmware includes the following pieces:
  • The 'Chapter 9' standard protocol support. The name comes from the set the messages being described in Chapter 9 of the USB specification. This is a file called usb_ch9.asm.
  • The HID interface support. This file handles requests for information relating to the HID specification. This is a file called hidclass.asm.
  • The device descriptor. This file contains the data that will be sent to the host during the enumerator process. Most of the values are fully specified by the USB spec but the vendor id, product id and version number all specified here. Importantly, the HID descriptor is stored in this file. This file is called descriptors.asm (also known as usb_mouse.asm). The version you download identifies the device as a mouse to the host.
  • The demo program. This program sets up the interrupts and initializes the USB code. It also runs through a loop that causes the cursor to move in a box shape on the screen. This program demonstrates how you use the USB specific functions to communicate with the host. This file is called main.asm (also known as usb_main.asm).
  • There is also a definitions include file called usb_defs.inc.
  • The entire project has an MPLAB project file (usbmic.pjt)
Warning: It has been a long time since I've worked on this project so I do not know if these files are complete or if they can be compiled directly.
Try to understand how the usb_main.asm file works. A couple of gotchas that you should watch out for are:
  • Triple check that the HID descriptor you are using matches the one you design in the HID Descriptor Tool. Even a single difference in a hex value will cause a failure in the enumeration process.
  • If you are using a HID descriptor, make sure that the number of bytes described in your descriptor is exactly the same as the number of bytes you are actually sending.
I used the PIC-Start programmer available from Microchip to program the 16C745.  Because this chip is not available in a flash version, a UV light is also required in order to erase the program before it can be reprogrammed.  If you are looking for a suitable third party programmer, look for those that have an external power supply of at least 12V.  Programmers that are powered from the USB or Serial port are NOT powerful enough for the non-flash microprocessors such as the 16C745.  I have used a programmer from http://www.kitsrus.com/ with success and they have programmers suitable for the 16C745.
To top.

Host Computer Code

Once a have is connect, you want to send and receive data from your applications. This document describes how you can do with using C in Visual C++. It is also possible to do this in Visual Basic (see below)

The following examples assume you are using Windows 2000. It should also work on Windows 98 but I'm not sure what the differences might be. Windows 95 did not fully support USB.  Linux also supports USB HID.
More information on these Windows API calls are available on the Microsoft web site. I used to have links directly to the appropriate page on the Microsoft MSDN website but Microsoft, in their wisdom, rearrange their website every 6 months or so, breaking all the links.  Compiling code to use these function calls requires that you install the Windows DDK (Device Development Kit) which used to be freely available from the Microsoft website (see below obtaining copies of the required dlls and header files.)
  • HidD_GetHidGuid (GUID *hidGUID)
  • HDEVINFO SetupDiGetClassDevs (GUID hidGUID, PSTR *filterString, hwndParent, DWORD flags)
  • BOOL SetupDiEnumDeviceInterfaces (infoset, infoData, interfaceClassGuid, index, deviceInterfaceData)
  • BOOL SetupDiGetDeviceInterfaceDetail (infoSet, deviceInterfaceData, interfaceDetail, interfaceDetailSize, requiredSize, infoData)
  • HANDLE CreateFile (name, access, sharemode, security, creation, flags, template)
  • BOOL HidD_GetAttributes (deviceHandle, &deviceAttributes))
See the example code below for details on using these methods.
To top.

Visual Basic Code

Even though Visual Basic does not allow direct access to the API calls, you can convert the API calls into visual basic functions. A good source of examples is at the web site for the book USB by Example[1]. The files HIDinterface.bas and OSinterface.bas available from the book's web site demonstrate using the API calls in Visual Basic.
To top.
-

Example Host Code

I have put together some library code which uses the above api's to connect to available HID USB devices.  The code returns a file handle to the USB device which allows a program to read and write data with the device just like with a regular file handle.  Note that this code is not a fully working program - it requires, at the minimum, a main function.
These file are known to compile under Visual C++ 5.0 on Windows 2000 with the Windows DDK installed. Make sure that the path to the file 'setupapi.h' is in your header file path (Project->Settings). You will also need to add 'setupapi.lib' and 'hid.lib' to list of libraries and ensure the path to these files is added to the library path for your project.
The code samples are:
You can either download the complete Windows DDK (which used to be available free from the Microsoft Website at http://www.microsoft.com/ddk/W2kDDK.htm or download just the few files actually needed for the sample code. These are from the Microsoft DDK which used to be freely available.
One person who found my code useful optimized my example code which removes some of the dependencies on the Windows DDK.  See Ross Bencina's P5 Glove Project for details.

A visitor to my site, Jim Koornneef, has provided a C++ class wrapper for my code that you can download from usb.h and usb.cpp.  This class encapsulates the functionality in my code but also provides read/write methods and automatic connect/disconnect functionality.
To top.

Project Hardware

This section describes the hardware specific to my project.  Please note that the focus of this page is on the USB aspects of the project.  My understanding is that the analog circuity for the microphone is not well designed.
The analog signal from the microphone was amplified using an op-amp and then digitized using the 16C745's analog-to-digital feature.  If you are reproducing this project, I would recommend putting in a filter to remove the frequencies higher than the microprocessor's sampling rate.  The digital data was buffered in the microprocessor and then set to the host computer over the USB connection.  Since 'interrupt' method of transfer only allows 8 bytes of data transfered every 10ms, this limited the amount of data that could be transfered.
The following circuit connects the PIC to the usb cable. It is designed to be powered off the USB cable. The 6 MHz clock controls the internal oscillator.

The 'reset' switch, causes a reset condition which should cause most of the special registers to clear and the program to start again.

The value of R1 is not critical since it is only used as a pull-up for the MCLR (master clear) pin. The R2 resister is required by the USB specification and should be 1.5 kOhms. The capacitor C3, is not critical and simply stabilizes the Vusb pin voltage. The values of the capacitors, C1 and C2 can be in a range specified in the 16C745 specification (15pf - 69 pf) and may depend on the crystal that you use.

Check that USB power and ground connections are correct before connecting the chip. It is easy to get turn around between the cable pinout and the socket pin out.
Circuit Diagram showing USB connections
The following circuit is used to power the electret microphone and then amplify the signal. The output signal is connected to one of the analog pins of the 16C745, we used pin 2, corresponding to AN0 (analog pin 0).
Microphone Powering Circuit

The components are
  • OP1 - a TLE2141 Op Amp. This comes in an 8 pin package with GND at pin 4, Power at pin 7, IN- at pin 2, IN+ at pin 3, and output at pin 6.
  • R1 - 1 kOhm resister
  • R2 - 3.2 kOhm resister
  • R3 - 1 kOhm resister
  • R4 - 500 kOhm resister
  • C1 - 0.005 uF capacitor
  • MIC1 - a electret microphone
The left side of the circuit is copied from http://www.hut.fi/Misc/Electronics/circuits/microphone_powering.html and the right side amplifies the signal 500 times (1 + R4/R3) using the op amp.
Update: a visitor to the site made the following suggestion to improve the circuit to allow the Op Amp to amplify the negative portion of the signal. 'Romano' said, "You should (if you want, of course), put a resistor between (+) of op-amp and Vcc, call it R2a, 6.8kohm will be good. R2 should be 6.8k again, so without mic signal you will have Vcc/2 at (+). Finally disconnect R3 from GND and put a capacitor (1uf or more) between R3 and GND. Without signal you will get Vcc/2 at the input of A/D."
Further update (06/09/27): Tito wrote me to suggest improvements to the amplifer. He made the following suggestion, "I noticed that your audio amplifier is not well polarized. I think it has big distortions because it only amplifies the positive part of the signal. I recommend using a negative amplifier configuration for the OPAMP. You just need to add a voltage divisor and a filter to polarize the OPAMP inputs."
To top.

Links

  • The book USB by Example by John Hyde. The companion web sites are at www.usb-by-example.com and http://www.intel-u-press.com/usb_dbe/ have lots of examples.
  • The book USB Complete by Jan Axelson. This book covers similar material as above but has more on the HID class. The companion web site has lots of example code and further references.

Tuesday, April 12, 2011

C++字符串完全指南 - STL和ATL类


ref: 
STL类
STL只有一个字符串类,即basic_string。basic_string管理一个零结尾的字符数组。字符类型由模板参数决定。通常,basic_string被处理为不透明对象。可以获得一个只读指针来访问缓冲区,但写操作都是由basic_string的成员函数进行的。
basic_string预定义了二个特例:string,含有char类型字符;which,含有wchar_t类型字符。没有内建的TCHAR特例,可用下面的代码实现:
// 特例化
typedef basic_string tstring; // TCHAR字符串
// 构造
string str = "char string"; // 从LPCSTR构造
wstring wstr = L"wide char string"; // 从LPCWSTR构造
tstring tstr = _T("TCHAR string"); // 从LPCTSTR构造
// 数据萃取
LPCSTR psz = str.c_str(); // 指向str缓冲区的只读指针
LPCWSTR pwsz = wstr.c_str(); // 指向wstr缓冲区的只读指针
LPCTSTR ptsz = tstr.c_str(); // 指向tstr缓冲区的只读指针
与_bstr_t 不同,basic_string不能在字符集之间进行转换。但是如果一个构造函数接受相应的字符类型,可以将由c_str()返回的指针传递给这个构造函数。例如:
// 从basic_string构造_bstr_t 
_bstr_t bs1 = str.c_str();  // 从LPCSTR构造 _bstr_t
_bstr_t bs2 = wstr.c_str(); // 从LPCWSTR构造 _bstr_t
ATL类
CComBSTR
CComBSTR 是ATL的BSTR包装类。某些情况下比_bstr_t 更有用。最主要的是,CComBSTR允许操作隐含BSTR。就是说,传递一个CComBSTR对象给COM方法时,CComBSTR对象会自动管理BSTR内存。例如,要调用下面的接口函数:
// 简单接口
struct IStuff : public IUnknown
{
  // 略去COM程序...
  STDMETHOD(SetText)(BSTR bsText);
  STDMETHOD(GetText)(BSTR* pbsText);
};
CComBSTR 有一个BSTR操作方法,能将BSTR直接传递给SetText()。还有一个引用操作(operator &)方法,返回BSTR*,将BSTR*传递给需要它的有关函数。
CComBSTR bs1;
CComBSTR bs2 = "new text";
pStuff->GetText ( &bs1 );       // ok, 取得内部BSTR地址
  pStuff->SetText ( bs2 );        // ok, 调用BSTR转换
  pStuff->SetText ( (BSTR) bs2 ); // cast ok, 同上
CComVariant 
CComBSTR有类似于 _bstr_t 的构造函数。但没有内建MBCS字符串的转换函数。可以调用ATL宏进行转换。
// 构造
CComBSTR bs1 = "char string"; // 从LPCSTR构造
CComBSTR bs2 = L"wide char string"; // 从LPCWSTR构造
CComBSTR bs3 = bs1; // 拷贝CComBSTR
CComBSTR bs4;
bs4.LoadString ( IDS_SOME_STR ); // 从字符串表加载
// 数据萃取
BSTR bstr1 = bs1; // 返回内部BSTR,但不可修改!
BSTR bstr2 = (BSTR) bs1; // cast ok, 同上
BSTR bstr3 = bs1.Copy(); // 拷贝bs1, 返回BSTR
BSTR bstr4;
bstr4 = bs1.Detach(); // bs1不再管理它的BSTR
// ...
SysFreeString ( bstr3 );
SysFreeString ( bstr4 );
上面的最后一个示例用到了Detach()方法。该方法调用后,CComBSTR对象就不再管理它的BSTR或其相应内存。所以bstr4就必须调用SysFreeString()。
最后讨论一下引用操作符(operator &)。它的超越使得有些STL集合(如list)不能直接使用CComBSTR。在集合上使用引用操作返回指向包容类的指针。但是在CComBSTR上使用引用操作,返回的是BSTR*,不是CComBSTR*。不过可以用ATL的CAdapt类来解决这个问题。例如,要建立一个CComBSTR的队列,可以声明为:
  std::list< CAdapt> bstr_list;
CAdapt 提供集合所需的操作,是隐含于代码的。这时使用bstr_list 就象在操作一个CComBSTR队列。
CComVariant
CComVariant 是VARIANT的包装类。但与 _variant_t 不同,它的VARIANT不是隐含的,可以直接操作类里的VARIANT成员。CComVariant 提供多种构造函数和多类型操作。这里只介绍与字符串有关的操作。
// 构造
CComVariant v1 = "char string";       // 从LPCSTR构造
CComVariant v2 = L"wide char string"; // 从LPCWSTR构造
CComBSTR bs1 = "BSTR bob";
CComVariant v3 = (BSTR) bs1;          // 从BSTR拷贝
// 数据萃取
CComBSTR bs2 = v1.bstrVal;            // 从VARIANT提取BSTR
跟_variant_t 不同,CComVariant没有不同VARIANT类型之间的转换操作。必须直接操作VARIANT成员,并确定该VARIANT的类型无误。调用ChangeType()方法可将CComVariant数据转换为BSTR。
CComVariant v4 = ... // 从某种类型初始化 v4
CComBSTR bs3;
if ( SUCCEEDED( v4.ChangeType ( VT_BSTR ) ))
    bs3 = v4.bstrVal;
跟 _variant_t 一样,CComVariant不能直接转换为MBCS字符串。要建立一个过渡的_bstr_t 变量,用其它提供转换Unicode到MBCS的类函数,或ATL转换宏来转换。
ATL转换宏
ATL的字符串转换宏可以方便地转换不同编码的字符,用在函数中很有效。宏按照[source type]2[new type] 或 [source type]2C[new type]格式命名。后者转换为一个常量指针 (名字内含"C")。类型缩写如下:

 A:MBCS字符串,char* (A for ANSI) 
 W:Unicode字符串,wchar_t* (W for wide) 
 T:TCHAR字符串,TCHAR* 
 OLE:OLECHAR字符串,OLECHAR* (实际等于W) 
 BSTR:BSTR (只用于目的类型)
例如,W2A() 将Unicode字符串转换为MBCS字符串,T2CW()将TCHAR字符串转换为Unicode字符串常量。
要使用宏转换,程序中要包含atlconv.h头文件。可以在非ATL程序中使用宏转换,因为头文件不依赖其它的ATL,也不需要 _Module全局变量。如在函数中使用转换宏,在函数起始处先写上USES_CONVERSION宏。它表明某些局部变量由宏控制使用。
转换得到的结果字符串,只要不是BSTR,都存储在堆栈中。如果要在函数外使用这些字符串,就要将这些字符串拷贝到其它的字符串类。如果结果是BSTR,内存不会自动释放,因此必须将返回值分配给一个BSTR变量或BSTR的包装类,以避免内存泄露。
下面是若干宏转换示例:
// 带有字符串的函数:
void Foo ( LPCWSTR wstr );
void Bar ( BSTR bstr );
// 返回字符串的函数:
void Baz ( BSTR* pbstr );
#include 
main()
{
using std::string;
USES_CONVERSION;    // 声明局部变量由宏控制使用
// 示例1:送一个MBCS字符串到Foo()
LPCSTR psz1 = "Bob";
string str1 = "Bob";
Foo ( A2CW(psz1) );
  Foo ( A2CW(str1.c_str()) );
// 示例2:将MBCS字符串和Unicode字符串送到Bar()
LPCSTR psz2 = "Bob";
LPCWSTR wsz = L"Bob";
BSTR bs1;
CComBSTR bs2;
bs1 = A2BSTR(psz2);         // 创建 BSTR
  bs2.Attach ( W2BSTR(wsz) ); // 同上,分配到CComBSTR
Bar ( bs1 );
  Bar ( bs2 );
SysFreeString ( bs1 );      // 释放bs1
  // 不必释放bs2,由CComBSTR释放。
// 示例3:转换由Baz()返回的BSTR
BSTR bs3 = NULL;
string str2;
Baz ( &bs3 );          // Baz() 填充bs3内容
str2 = W2CA(bs3);      // 转换为MBCS字符串
  SysFreeString ( bs3 ); // 释放bs3
}

可以看到,向一个需要某种类型参数的函数传递另一种类型的参数,用宏转换是非常方便的。

Tuesday, April 5, 2011

校验知识:CRC32、MD5、SHA1概念及可靠性现状

Ref: http://www.metsky.com/archives/337.html
1、CRC校验
CRC全称Cyclic Redundancy Check,又叫循环冗余校验。它是一种散列函数(HASH,把任意长度的输入通过散列算法,最终变换成固定长度的摘要输出,其结果就是散列值,按照HASH算法,HASH具有单向性,不可逆性),用来检测或校验传输或保存的数据错误,在通信领域广泛地用于实现差错控制,比如通信系统多使用CRC12和CRC16,XMODEM使用CRC16等等(12、16、32等值均是指多项式的最高阶N次幂),天缘早前在做通信方面工作时也是最常用到这个校验方法,因为其编解码方法都非常简单,运算时间也很短。
但从理论角度,CRC不能完全可靠的验证数据完整性,因为CRC多项式是线性结构,很容易通过改变数据方式达到CRC碰撞,天缘这里给一个更加通俗的解释,假设一串带有CRC校验的代码在传输中,如果连续出现差错,当出错次数达到一定次数时,那么几乎可以肯定会出现一次碰撞(值不对但CRC结果正确),但随着CRC数据位增加,碰撞几率会显著降低,比如CRC32比CRC16具有更可靠的验证性,CRC64又会比CRC32更可靠,当然这都是按照ITU规范标准条件下。
正因为CRC具有以上特点,对于网络上传输的文件类很少只使用CRC作为校验依据,文件传输相比通信底层传输风险更大,很容易受到人为干预影响。

2、MD5
MD全称Message Digest,又称信息摘要算法,MD5从MD2/3/4演化而来,MD5散列长度通常是128位, 也是目前被大量广泛使用的散列算法之一,主要用于密码加密和文件校验等。MD5的算法虽然非常“牢靠”,不过也已经被找到碰撞的方法,网上虽然出现有些碰撞软件,天缘没用过,但可以肯定,实际作用范围相当有限,比如,及时黑客拿到了PASSWORD MD5值,除了暴力破解,即使找到碰撞结果也未必能够影响用户安全问题,因为对于密码还要限定位数、类型等,但是如果是面向数字签名等应用,可能就会被破解掉,不过,MD5同下文的SHA1仍是目前应用最广泛的HASH算法,他们都是在MD4基础上改进设计的。

3、SHA1
SHA全称Secure Hash Standard,又称安全哈希标准,SHA家族算法有SHA-1、SHA-224、SHA-256、SHA-384和SHA-512(后四者通常并称SHA2),原理和MD4、MD5原理相似,SHA是由美国国家安全局(NSA)所设计,由美国国家标准与技术研究院(NIST)发布。SHA可将一个最大2^64位(2305843009213693952字节)信息,转换成一串160位(20字节)的散列值(摘要信息),目前也是应用最广泛的HASH算法。同MD5一样,从理论角度,SHA1也不是绝对可靠,目前也已经找到SHA1的碰撞条件,但“实用”的碰撞算法软件还没出现。于是美国NIST又开始使用SHA2,研究更新的加密算法。
校验工具下载:

三 款主流文件校验码工具HashCalc、WinMD5、Hasher

补 充
1、上文“碰撞”的解释,碰撞就是不同明文通过HASH后的结果相同。
2、MD5和SHA1都具有高度的离散性,哪怕是只修改一个字节值都会导致MD5或SHA1值“巨大”变化,从实践角度,不同信息具有相同MD5或SHA1码 的可能性非常低,通常认为是不可能的。
3、对于普通的下载文件或操作系统,想通过简单的修改某个字节或某些字节,又要保证文件名、大小和安装可靠性的前提下,想达到MD5、SHA1碰撞效果也几乎是不可能的。
4、关于单线程下载和多线程下载是否会对下载文件的准确性有影响,像电驴、迅雷都是按照HASH码进行合法校验“拼装”的,除非是软件出了错误,否则单线程多线程跟最终下载结果没有区别,从微软服务器下载跟从山寨网站下载结果也没有区别。
5、总之,有生之年,大家可以不相信CRC,但是MD5和SHA1绝对值得信赖,敬请放心,他们比天气预报要可靠的多了。
参考资料:维基百科——CRC循环冗余校验,MD5,SHA

Tuesday, March 8, 2011

Java and USB

Java and USB

来自:http://today.java.net/pub/a/today/2006/07/06/java-and-usb.html?page=2

Although the Universal Serial Bus (USB) is an integral part of many computers, Java does not officially support USB. Getting your Java programs to interact with arbitrary USB devices thus requires either a third-party Java/USB API or your own Java/USB API. This article introduces two third-party APIs and my own API, which provides a partial USB interaction.

Before it introduces the APIs, this article explores some USB fundamentals. The article next introduces JSR-80 (an API that attempts to bring official USB support to Java) and jUSB (a rival API). Moving on, the article presents my own bus-enumeration API, which only works in a Windows context. The article closes by pondering whether or not Java should officially support the USB.

I developed and tested this article's code with Sun's J2SE 5.0 SDK and Borland C++ 5.5.1. Windows 98 SE and Windows ME were the underlying OSes.
USB in a Nutshell

USB is a serial bus standard for connecting devices to computers, video game consoles, televisions, and so on. This standard has advantages over the legacy personal computer (PC) architecture (expansion cards, I/O ports, interrupts, device drivers) previously used to connect devices to PCs. These advantages include:

*

The serial bus, in partnership with plug and play, eliminates I/O port and interrupt conflicts that often arise when adding new devices to a legacy PC.
*

There is no need to open a USB-enabled PC and insert expansion cards into its system bus. Devices plug into the serial bus through external connectors.
*

Devices can be connected to or removed from the serial bus without having to first power down or reboot the USB-enabled PC. This is known as hot swapping.

Compaq, Intel, Microsoft, and NEC started to work on the USB standard in 1994. In January 1996, they released version 1.0. Following revisions, these companies released version 1.1 in September 1998. And in April 2000, after Hewlett-Packard, Lucent, and Philips joined the group, version 2.0 was released.

USB 1.1 was the first widely implemented version of the USB standard. It featured two data-transfer speeds: full speed (12 megabits per second) and low speed (1.5 megabits per second). It is now fading into history as version 2.0 takes over. This version adds a third data-transfer speed: high speed (480 megabits per second).

To fully understand the USB standard, you'll need to review the USB 1.1 specification and the USB 2.0 specification. For the purpose of understanding this article, however, you only need to grasp a few fundamentals, starting with an overview of host controllers, hubs, and functions.
Host Controllers, Hubs, and Functions

USB is implemented in terms of software drivers (which I don't discuss here) and hardware. The hardware divides into host controllers, hubs, and functions:

*

The host controller connects a tree of USB devices to a host (computer, console, and so on). Multiple host controllers can be present. Each host controller anchors one device tree.
*

A hub is a device with multiple ports, into which are plugged other hubs and functions. The root hub integrates with the host controller. All other hubs are external hubs.
*

A function is a device that provides a capability to the host. It plugs into a hub (external or root). Mice, keyboards, cameras, scanners, and printers are examples.

This hardware arranges into a tiered-star topology where each star's center is a hub: both the root hub and external hubs sit at the center of their connected external hubs/functions. Figure 1 reveals this topology.

Three external hubs
Figure 1. Three external hubs (Hub 1/Hub 2/Hub 3 or Hub 1/Hub 2/Hub 4) are chained together from the root hub

Configurations, Interfaces, and Endpoints
Configurations, Interfaces, and Endpoints

A function can have one or more configurations that control how the function behaves. Configurations can differ in how much power they consume, whether and how they remotely wake up a suspended computer, and more.

A trackball device that can be configured as a mouse or as a joystick is an example of a function with multiple configurations. Another example is an Integrated Services Digital Network (ISDN) communications device that offers one 128Kb channel or two 56Kb channels.

Each configuration contains one or more interfaces that specify how software accesses the hardware. Interfaces frequently have alternate settings corresponding to different bandwidth requirements.

An interface exposes endpoints that each serve as a data transfer source or a data transfer destination. Each endpoint supports data transfer in a single direction and has a unique numeric identifier. Figure 2 relates endpoints to interfaces and configurations.

The relationship between a function's configurations, interfaces, and endpoints
Figure 2. The relationship between a function's configurations, interfaces, and endpoints

Note: Microsoft drivers tend to work with only the first configuration. As a result, multi-configuration functions are rare and are discouraged by Microsoft.
Data Flow Model

USB supports the flow of data between applications running on a host and physical devices attached to the USB. This data flow can be understood in terms of a data flow model--such as Figure 3's USB data flow model.

The USB data flow model divides into three layers
Figure 3. The USB data flow model divides into three layers

Actual data transfers take place in a physical device's lowest bus layer. This layer consists of the hubs and cables (and associated connectors) that connect the host controller to the physical device's bus interface.

Data physically flows vertically up and down both sides of the model. Data virtually flows horizontally across the corresponding sides of the upper two layers by way of pipes, logical channels that associate host software memory buffers with endpoints.

Pipes can be categorized as message pipes and stream pipes. Message pipes transfer data with some USB structure. In contrast, stream pipes transfer data with no USB structure.

The device layer has a logical view of and controls the physical device. It uses a special message pipe, the Default Control Pipe, to read configuration data from input endpoint 0 and output control data to output endpoint 0. These endpoints are always present.

The function layer has a function view of the physical device. This layer uses data pipes (stream pipes) to transfer data to and from the function.
Transfer Types

A pipe transfers data according to an endpoint's transfer type, which governs how much data transfers in a transaction (part of a data transfer), whether or not the transfer is lossless, and other factors:

*

Bulk transfers are used to transfer files and perform other kinds of transfers that involve large blocks of unstructured data. These transfers guarantee that all data will be delivered.
*

Control transfers are used to control the physical device. These transfers send and receive structured data in the form of commands and statuses.
*

Isochronous transfers are used to transfer realtime audio, video, and other kinds of unstructured data at a guaranteed speed. However, there is the possibility of data loss.
*

Interrupt transfers are used by pointing devices, keyboards, and any other physical devices that need a guaranteed quick response. Interrupt transfers are similar to bulk transfers.

Note: Although I don't focus on data transfer in this article, you need to be aware of these transfer types when working with the JSR 80 and jUSB APIs.
Descriptors

USB devices present onboard data structures known as descriptors. These data structures let a device's function (or functions) identify itself (or themselves) to software running on the host:

*

Device descriptors describe an entire device.
*

Device qualifier descriptors are used with USB 2.0 devices.
*

Configuration descriptors describe a device's configurations.
*

Other speed configuration descriptors are used with USB 2.0 devices.
*

Interface descriptors describe a configuration's interfaces.
*

Endpoint descriptors describe an interface's endpoints.
*

String descriptors contain human-readable Unicode strings that each describe a device, a configuration, an interface, or an endpoint.

Later in this article, I present a bus-enumeration example, whose C++ code accesses device and string descriptors during the enumeration process.
Device Classes

USB devices belong to device classes, which define an expected behavior in terms of device and interface descriptors. A device class's device driver can be used for any device belonging to the device class.

OSes usually provide generic drivers for all device classes, to support all USB devices. When a device attaches to the USB, its device class identifier is read from a specific descriptor and used to load the proper driver.

The USB-IF standardizes device class identifiers. Examples include 1 (audio class: a sound card), 3 (human interface device class, such as keyboards and mice), 8 (mass storage device class: flash drives and portable hard drives), and 9 (hub class). Identifiers 0 and 255 are reserved.

If the class belongs to the entire device, the identifier is assigned to the device descriptor's 8-bit bDeviceClass field. If the class is for a single interface, the identifier is assigned to the interface descriptor's 8-bit bInterfaceClass field (0 is assigned to bDeviceClass).
JSR-80

In 1999, IBM's Dan Streetman began a Java/USB API project to let Java programs interact with the USB. In 2001, via the Java Community Process (JCP), this project was accepted as a candidate standard extension to the Java language. The JCP identifies this project as Java Specification Request (JSR) 80--you can determine JSR 80's current status by visiting the

The official development site for JSR 80 is

The Linux implementation has been certified with Sun's test compliance kit. You'll find this implementation's C and Java source files, and a Linux-specific javax.usb.properties file, in the repository's javax-usb-ri-linux directory tree. It appears that you will have to build this implementation from the source code (assuming that Linux is your OS).

The pre-alpha Windows implementation is not certified and requires a kernel driver. This implementation's C and Java source files, and a Windows-specific javax.usb.properties file, are located in the repository's javax-usb-ri-windows directory tree. If Windows is your OS, you can build this implementation from the source code (after possibly making changes), but you must supply the kernel driver.

You might prefer the alpha Windows implementation. This uncertified implementation is located in the repository's javax-usb-libusb directory tree. Along with deployment files, you'll need to install the Windows version of libusb. Visit the libusb Project Page and the libusb-win32 Project Page to learn about libusb and obtain the Windows version.

The JSR 80 API specification PDF document, located in the repository as jsr80.pdf, describes this API's architecture. This document reveals that the USBHostManager class is the entry point into the API. This class lets you obtain an OS-specific instance of the USBServices interface (based on information in javax.usb.properties), from which you can obtain the virtual root hub:

UsbServices services =
UsbHostManager.getUsbServices ();
UsbHub vroothub = services.getRootUsbHub ();

The virtual root hub, obtained by calling UsbServices's public UsbHub getRootUsbHub() method, provides access to all of the available host controllers (and their root hubs). UsbHub's public boolean isRootUsbHub(), public byte getNumberOfPorts(), and public List getUsbPorts() methods are useful in verifying, enumerating, and obtaining root hubs.

I won't dig deeper into JSR 80 because "Access USB Devices from Java Applications" presents a nice overview of this API. This overview includes example bus-enumeration and data-transfer code, which demonstrates obtaining an endpoint's transfer type, direction, and connected pipe. Instead, I've identified four tasks that you need to perform to achieve a successful installation of JSR 80 on your OS:

*

Add jsr80.jar to your CLASSPATH. Your Java programs interact with this .jar file's classes and interfaces. You can find jsr80.jar in the javax-usb-libusb directory's lib directory.
*

Add jsr80_ri.jar to your CLASSPATH. Almost all of the javax.usb API is implemented in this .jar file. You can also find jsr80_ri.jar in the javax-usb-libusb directory's lib directory.
*

Install either the Linux or Windows libusb implementation. For Windows libusb, don't forget to install the Windows version of libusb. Furthermore, you must also add jsr80_windows.jar to your CLASSPATH when installing the Windows libusb implementation. This .jar file is in the previous lib directory.
*

Add the appropriate javax.usb.properties file (either the Linux or Windows libusb version) to your CLASSPATH. This file contains a javax.usb.services property, which identifies the fully qualified name of a class that implements the javax.usb.UsbServices interface. This class is the entry point to the Linux and Windows implementations.

The lib directory also contains log4j.properties, along with the commons_logging.jar and log4j.jar jar files. I believe you can avoid adding these .jar files to your CLASSPATH by modifying the javax.usb.properties file.
jUSB

"Mojo Jojo" and David Brownel began a rival Java/USB API project in June 2000: jUSB. They developed a version for Linux, which is available from their project page. For his thesis, Mike Stahl created a Windows version; visit the jUSB: Java USB API for Windows project page to obtain this version. jUSB is licensed under the Lesser GNU Public License.

While researching jUSB, I focused on Mike's Windows version. From Mike's jUSB site, I downloaded two archives: JavaUSB.zip and JavaUSBComplete.zip. The former archive contains the Java source code to jUSB's packages, the jUSB DLL, and the jUSB kernel driver (along with information and registry files) for Windows XP and Windows 2000. The latter archive includes the DLL and driver source code.

I also downloaded Mike's "Java USB API for Windows" diploma thesis--a 2.2MB PDF file. This PDF file introduces the USB and provides a detailed account of how Mike implemented jUSB's usb.windows package for Windows 2000 and Windows XP. This document is a must-read for anyone wanting to create a Java/USB API that accesses the Windows USB architecture.

According to Mike's thesis, jUSB's usb.core package contains a HostFactory class, whose public static Host getHost() method is the entry point into jUSB. This method returns a Host object, which monitors all busses (device trees) on a given machine. Rather than dig deeper into jUSB, I recommend exploring jUSB in "Access USB Devices from Java Applications."
Create Your own Java/USB API

Although you can use the JSR 80 and jUSB APIs to give your Java programs the ability to interact with USB, you might decide to create something different. To help you with this task, I present my own API. This API is limited to bus enumeration. Furthermore, the Java Native Interface (JNI) C++ code limits the API to Windows 98 SE, Windows ME, and (although it has not been tested) Windows 2000.

I built the API's C++ code using the Borland C++ 5.5.1 compiler. You'll need to obtain a copy of this compiler (which is free) if you plan to modify the code--I provide a prebuilt DLL with this article's code (see Resources). Click the Compiler link in the Downloads table on the C++ Builder Downloads--Borland C++ 5.5.1 compiler page to obtain Borland C++ 5.5.1.

My "Java Tech: Acquire Images with TWAIN and SANE, Part 1" article, which I wrote for java.net, briefly introduces Borland C++ 5.5.1. For a more substantial introduction, check out "Get Acquainted with Borland C++ 5.5.1" in my article "Build Screensavers with a Custom Screensavers Library in Borland C++."
JavaUSB

My JavaUSB API consists of five top-level unpackaged classes: JavaUSB, HCInfo, Device, Hub, and Function. Consider placing these classes into their own package. The JavaUSB class serves as the entry point into this API. It provides three methods that load a DLL and access DLL functions:

*

public static boolean init() initializes JavaUSB by loading javausb.dll. It returns Boolean true if the DLL successfully loads. If an UnsatisfiedLinkError occurs, false returns. You must call this method before calling the other two methods.
*

public static native HCInfo getHostControllerInfo(int index) returns an HCInfo object that provides the name of the indexth host controller and the name of its root hub. Indexes start at 0; null is returned if no host controller associates with index.
*

public static native Device [] getAttachedDevices(String hubName) returns an array (possibly with zero length) of all Devices currently attached to the hub identified by hubName; null is returned if this method cannot accomplish its task.

To keep JavaUSB simple, I haven't provided an exception class and modified each native method to throw an instance of this class whenever something goes wrong. However, these methods can throw JNI-related errors ("classfile not found," for example). Instead, a problem is revealed when the native method returns a null value. Consider enhancing these methods to throw a suitable exception.

HCInfo describes host controller information returned by the getHostControllerInfo() method. This information is stored in two String fields: name contains the host controller's name and rootHubName contains the host controller's integrated root hub's name. Pass the rootHubName field to getAttachedDevices() to begin enumerating a device tree.

Device describes one of the hub or function devices that is attached to a hub. This class contains three String fields that are common to hubs and functions: manufacturer identifies the device's manufacturer, product identifies the device as a product, and serialNumber identifies the device's serial number. These fields may be null.

Device is also the abstract superclass for the Hub and Function classes. The Hub class presents a single String field, hubName, that names an external hub. In contrast, Function is an empty class. In the future, I plan to expand Hub and Function with fields and methods that are unique to these classes.

To demonstrate how easy JavaUSB's classes and the JavaUSB class's three methods are to use, I have created a TestJavaUSB application. This application's source code employs four of the classes (there is no point in using Function until this class is more fully developed) to enumerate each host controller's root hub's device tree. The application's source code is presented below.

// TestJavaUSB.java

public class TestJavaUSB
{
public static void main (String [] args)
{
// Attempt to initialize the JavaUSB
// library.

if (!JavaUSB.init ())
{
System.err.println ("Unable to " +
"initialize JavaUSB");
return;
}

// Enumerate all attached host controllers,
// outputting their names and the names of
// their root hubs. For each root hub,
// enumerate the device tree.

for (int i = 0; ; i++)
{
HCInfo hcinfo =
JavaUSB.getHostControllerInfo (i);
if (hcinfo == null)
break;

System.out.println ("\nHost " +
"controller name = " + hcinfo.name);
System.out.println ("Root hub " +
"name = " + hcinfo.rootHubName);

enumerate (hcinfo.rootHubName, 1);
}
}

public static void enumerate (String hubname,
int depth)
{
Device [] devices =
JavaUSB.getAttachedDevices (hubname);
if (devices == null)
return;

for (int i = 0; i < devices.length; i++)
{
System.out.println ();

for (int j = 0; j < depth; j++)
System.out.print (' ');

System.out.println (devices [i]);

for (int j = 0; j < depth; j++)
System.out.print (' ');

System.out.printf ("Manufacturer = %s\n",
devices [i].manufacturer);

for (int j = 0; j < depth; j++)
System.out.print (' ');

System.out.printf ("Product = %s\n",
devices [i].product);

for (int j = 0; j < depth; j++)
System.out.print (' ');

System.out.printf ("Serial number " +
"= %s\n",
devices [i].serialNumber);

if (devices [i].isHub ())
enumerate (((Hub) devices [i]).
hubName, depth+1);
}
}
}

Executing java TestJavaUSB on my Windows 98 SE OS caused the following output to appear:

Host controller name = USB\0000
Root hub name = \\.\0000000000000007#{f18a0e88-c30c-11d0-8815-00a0c906bed8}

Function
Manufacturer = Microsoft
Product = Microsoft IntelliMouse® Explorer
Serial number = null

The output below appeared when I executed java TestJavaUSB under Windows ME OS:

Host controller name = USB\0002
Root hub name = \\.\0000000000000005#{f18a0e88-c30c-11d0-8815-00a0c906bed8}

Hub
Manufacturer = ALCOR
Product = Generic USB Hub
Serial number = ?

Function
Manufacturer = LEXAR MEDIA
Product = JUMPDRIVE
Serial number = L210442203100M

This source code raises an interesting question: What happens if a host controller is attached or removed during enumeration? For an attachment, I assume the OS will append a host controller entry to some structure of entries and enumeration will not be affected. For a removal, either the host controller was already enumerated or a native method will return null (depending on where the code is executing).
Under the Hood

JavaUSB works with Windows 98 SE and Windows ME. Although I haven't tested this API with Windows 2000 (I do not have access to this OS), I believe that JavaUSB works with Windows 2000. If you need to modify this API's javausb.cpp code to support another Windows OS (or even a non-Windows OS), you'll be interested in the following javausb.cpp details:

*

Various Windows Driver Development Kits (DDKs) define assorted constants, macros, and types for working with the USB. Rather than require you to install a copy of the DDK (the Windows 98 SE DDK is no longer available), I've created an extensively commented usb.h header file, with constants, macros, and types relevant to and included by javausb.cpp.
*

The javausb.cpp source code uses four Win32 API functions to interact with the Windows USB: CreateFile() (open a host controller or hub device), DeviceIoControl() (interact with the device), WideCharToMultiByte() (convert Unicode characters to ANSI 8-bit characters), and CloseHandle() (close the device).
*

Windows 98 SE, Windows ME, and Windows 2000 use the \\.\HCDx syntax (x is a zero-based integer) to identify a host controller device. The first host controller's device name is \\.\HCD0, the second host controller's device name is \\.\HCD1, and so on. This device name is passed to CreateFile() to open the host controller.

For information on building javausb.dll with Borland C++ 5.5.1, examine the articles I referred to earlier. Also, read the comments in the makedll.bat file--included with this article's code.
Should Java Officially Support the USB?

While researching this article, I encountered various discussions on whether or not Java should officially support the USB. Several individuals want Sun to introduce USB support into Java, whereas other individuals do not think it's a good idea for Java to officially support the USB. Below are two typical reactions:

*

One respondent to JavaLobby's
*

According to one

If Java is to officially support the USB, this support should be present on all OSes that support Java--even on OSes that don't support the USB. After all, Java is a cross-platform technology. But what happens if a Java-supported OS supports FireWire (or some other technology) instead of the USB?

Some developers have expressed a desire to see Java support FireWire and Bluetooth (which I like to think of as a wireless USB) in addition to USB. Although JSR 82, Java APIs for Bluetooth, is in the works (there appears to be no FireWire JSR), does it make sense to have separate USB and Bluetooth APIs?

USB, FireWire, and Bluetooth are three technologies that communicate with devices. Because Java has a long history of abstracting over similar technologies, maybe it's feasible to devise a single serial-based API that abstracts over these and similar future technologies. Perhaps Java should officially support USB this way.
Conclusion

Because Java doesn't officially support USB, you need to work with JSR 80, jUSB, or some other third-party Java/USB API--or even create your own API--to bring USB interaction to your Java programs. Should you plan to create your own API for use with Windows, JavaUSB can help get you started with the bus-enumeration part. I deliberately avoided supporting data transfer for two reasons:

*

I don't want to support data transfer until I complete the bus-enumeration code. According to a Microsoft article, I need to use a technique based on globally unique identifiers (GUIDs) to ensure that USB 2.0 host controllers are enumerated on Windows 2000 (and possibly on Window 98 SE and Windows ME).
*

I need to create a kernel-mode driver to support data transfer on Windows. Although I recently obtained a copy of Walter Oney's highly-regarded book Programming the Microsoft Windows Driver Model (Microsoft Press, 2003), which explores kernel-mode driver creation, it will take time to fully absorb this book's content. If you're interested in the Microsoft Windows driver model, I recommend this book.

My work on JavaUSB has shown me that it's not easy to develop a Java/USB API. The API must be useful while not exposing low-level hardware details. It must also be abstract enough to be usable across OSes. Because I chose to target the Windows 98 SE/ME/2000 OSes (for practical reasons), I leave you with the following homework: try porting JavaUSB to Linux or some other OS.

What would you like to do with Java and cannot? topic wants Java to officially support the USB: "Seriously, Sun if you are reading this, pay attention! This [javax.comm] sucks badly. And while you're fixing serial port IO, how about getting USB and FireWire working while you're at it?"JCP home page for JSR 80 (Java USB API).java.net forum topic: USB support (especially for Windows) response, Java shouldn't officially support the USB because this is "similar to having direct access to the physical layer on network cards or directly accessing the SCSI bus." Furthermore: "You don't need direct USB access to use card readers or USB mass storage devices--that should be handled by the OS. You should be able to simply create a file in the appropriate section of the file system, write to it, and the OS should take care of the rest."JSR080 - javax.usb. This site provides links to the JSR 80's Common Public License, a FAQ, API implementations in the CVS repository, and Javadoc for the API. The repository provides jsr80.jar (the core javax.usb package implementation), jsr80_ri.jar (the OS-independent reference implementation), and Linux/Windows implementations.

Sunday, March 6, 2011

NFC

NFC technology is intended mainly for use in mobile phones. There are currently three specific uses for NFC:

* Card emulation: the NFC device behaves like an existing contactless card
* Reader mode: the NFC device is active and reads a passive RFID tag, for example for interactive advertising
* P2P mode: two NFC devices communicating together and exchanging information.

Plenty of applications are possible, such as:

* Mobile ticketing in public transport: an extension of the existing contactless infrastructure, such as Mobile Phone Boarding Pass.[2]
* Mobile payment: the device acts as a debit/credit payment card.
* Smart poster: the mobile phone is used to read RFID tags on outdoor billboards.
* Bluetooth pairing: in the future pairing of Bluetooth 2.1 devices with NFC support will be as easy as bringing them close together and accepting the pairing. The process of activating Bluetooth on both sides, searching, waiting, pairing and authorization will be replaced by a simply bringing the mobile phones close to each other.

Other applications in the future could include:

* Electronic ticketing: airline tickets,[2] concert/event tickets, and others
* Electronic money
* Travel cards
* Identity documents
* Mobile commerce
* Electronic keys: replacements for physical car keys, house/office keys, hotel room keys, etc.
* NFC can be used to configure and initiate other wireless network connections such as Bluetooth, Wi-Fi or Ultra-wideband.

Near Field Communication, or more commonly known as NFC, is a subset of RFID that limits the range of communication to within 10 centimeters or 4 inches.
For RFID, Malicious people can receive your information and clone it into another tag and use it for themselves. This is where NFC comes in.

1.NFC is just an extension to RFID technology
2.RFID is capable of accepting and transmitting beyond a few meters while NFC is restricted to within 4 inches
3.RFID has a wide range of uses while NFC is usually used in cases where security is needed

Thursday, March 3, 2011

在VC中使用自定义资源,FindResource,LoadResource,LockResource

一、前言
  在VC环境中除了我们所常用的Dialog、Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多。
1. 默认的皮肤压缩包或语言包。一些支持换肤的软件特别是一些媒体播放器常常有自定义的皮肤文件(你可以尝试将Media Player或千千静听等软件的Skins目录下的文件的扩展名改为.zip,然后使用WinZip打开看一下),但为了防止Skin文件丢失导致软件无法显示,他们常常会在EXE文件中内置一套Skin作为默认的皮肤文件。同样,一些支持多语言的EXE文件中存在默认语言包也是这个道理(当然也可以使用 "String Table"资源类型);
2. 做为一些病毒/木马程序的寄生方式。如果不小心执行了带有病毒/木马的程序,它们会在你运行时释放出病毒/木马文件。当然许多病毒是将自身写入PE文件头来实现;
3. 合并EXE与它所需要的DLL文件。出于某些原因程序作者有时可能需要将DLL文件嵌入到可执行的EXE文件中,这可以通过使用自定义资源来实现;
4. 其它需要在程序中播放一个AVI动画等等,都可以通过将二进制的数据文件作为自定义资源加入到可执行文件中来实现;

二、添加
  添加资源时选择自定义,IDE会为你生成一个新的二进制资源,然后你就可以将你已经存在的二进制文件作为自定义的资源类型导入到项目中来了。

三、使用
  要使用自定义资源,我们可能要用到的几个API函数有FindResource、LoadResource和LockResource等,这里每一个函数的返回值分别作为下一个函数的参数,我来简要介绍一下。
1. FindResource用来在一个指定的模块中定位所指定的资源:
             HRSRC FindResource(
             HMODULE hModule,                //包含所需资源的模块句柄,如果是程序本身,可以置为NULL
             LPCTSTR lpName,         //可以是资源名称或资源ID
             LPCTSTR lpType          //资源类型,在这里也就是我们自己指定的资源类型
             );     

      LoadResource用来将所指定的资源加载到内存当中;

             HGLOBAL LoadResource(
             HMODULE hModule,                //模块句柄,同上
             HRSRC hResInfo          //需要加载的资源句柄,这里也就是FindResource的返回值
          );             

   LockResource用来锁定内存中的资源数据块,它的返回值也就是我们要使用的直系指向资源数据的内存指针;

          LPVOID LockResource(
          HGLOBAL hResData                //指向内存中要锁定的资源数据块,这里也就是LoadResource的返回值
          );             
  另外我们还需要用SizeofResource来确定资源的尺寸,我们在操作资源时要用到它。在资源使用完毕后我们不需要使用 UnlockResource和FreeResource来手动地释放资源,因为它们都是16位Windows遗留下来的,在Win32中,在使用完毕后系统会自动回收。它们的使用很简单,大致上是这个样子的:
BOOL UseCustomResource()
{
        //定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可
        HRSRC hRsrc = Findresource(null, MAKEINTRESOURCE(ITEMID), TEXT("MyType"));
        if (NULL == hRsrc)
                return FALSE;
        //获取资源的大小
        DWORD dwSize = SizeofResource(NULL, hRsrc);
        if (0 == dwSize)
                return FALSE;
        //加载资源
        HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
        if (NULL == hGlobal)
                return FALSE;
        //锁定资源
        LPVOID pBuffer = LockResource(hGlobal);
        if (NULL == pBuffer)
                return FALSE;
       //我们用刚才得到的pBuffer和dwSize来做一些需要的事情。可以直接在内存中使
        //用,也可以写入到硬盘文件。这里我们简单的写入到硬盘文件,如果我们的自定
        //义资源是作为嵌入DLL来应用,情况可能要复杂一些。

        BOOL bRt = FALSE;
        FILE* fp = _tfopen(_T("demo.exe"), _T("wb"));
        if (fp != NULL)
        {
                if (dwSize == fwrite(pBuffer, sizeof(char), dwSize, fp))
                        bRt = TRUE;
                fclose(fp);
        }

        //FreeResource(hGlobal);
        return bRt;
}

Virtual Memory Layout: Windows CE 5.0 vs. Windows Embedded CE 6.0

Before Windows Embedded CE 6.0, there was a limit of 32 processes, and a 32 MB limit on virtual memory (VM) for each process. Also, all of the processes shared the same 4 GB address space. For CE 6.0, the kernel process resides in the upper 2 GB of the 4-GB (32-bit) virtual memory space, and the bottom 2 GB is unique for each process. There is a limit of about 32,000 processes, due to the number of handles that can be created. The practical limit on the number of processes is bounded by the amount of physical memory.

In WM 6.1, the CE version is 5.2.*.