<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7427153926913253228</id><updated>2012-01-30T22:02:34.816+08:00</updated><category term='LPR'/><category term='Lion'/><category term='OCR ANN CNN 卷积神经网络'/><category term='OpenCV'/><category term='Mac OS X'/><category term='Xlib XImage'/><category term='连通区域 深度优先搜索'/><category term='VOIP H323 SIP CTI'/><category term='Emacs'/><category term='full screen'/><category term='image processing'/><category term='Convolution'/><category term='memory leak'/><title type='text'>Fresh Technology Try</title><subtitle type='html'>Try something.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>60</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5996848938633776379</id><published>2011-12-05T12:07:00.001+08:00</published><updated>2011-12-05T13:26:16.154+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='full screen'/><category scheme='http://www.blogger.com/atom/ns#' term='Mac OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='Lion'/><category scheme='http://www.blogger.com/atom/ns#' term='Emacs'/><title type='text'>Emacs 24 on Lion - mention the top right corner - full screen support</title><content type='html'>Build Emacs on (Mac OS X 7) Lion, need get the latest code of emacs from the code repository.&lt;br&gt;(The latest stable release 23.3 can not be built on Lion, but 24.0.x is OK, &lt;br&gt;to build emacs 23.3 on Lion, check &lt;a href="http://yukei.blog.163.com/blog/static/11258770320111020105135468/"&gt;this&lt;/a&gt;.)&lt;br&gt;Using git to checkout the code, "git clone --depth 1 git://git.savannah.gnu.org/emacs.git"&lt;br&gt;"--depth 1" gets the latest code but not the whole history of repository.&lt;br&gt;&lt;br&gt;The newer m4, autoconf, automake, libtool are needed to build emacs code. &lt;br&gt;Lion has got these tools preinstalled but too old to build emacs code.&lt;br&gt;I download them from mirror.kernel.org. Download, build and install with the classic steps (configure, make, sudo make install).&lt;br&gt;Do not forget add /usr/local/bin to your bash PATH, otherwise the tools still are the older version of the system.&lt;br&gt;&lt;br&gt;&lt;br&gt;Patch emacs code with the Lion full screen features.&lt;br&gt;Get the patch file from git://gist.github.com/1355895.git.&lt;br&gt;It is really cool and straightforward.&lt;br&gt;&lt;br&gt;&lt;br&gt;Full screen support is a big favor to developer. Amazing feature, love Lion.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5996848938633776379?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5996848938633776379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5996848938633776379' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5996848938633776379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5996848938633776379'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2011/12/emacs-24-on-lion-mention-top-right.html' title='Emacs 24 on Lion - mention the top right corner - full screen support'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4323096950308185700</id><published>2009-04-24T22:14:00.002+08:00</published><updated>2009-04-24T22:18:04.026+08:00</updated><title type='text'>The HDA sound driver for my T61p</title><content type='html'>Eventually, I found the driver from google code. Thanks god. otherwise I need write this one.&lt;br /&gt;&lt;br /&gt;Please goto http://code.google.com/p/voodoohda/ get the latest code.&lt;br /&gt;&lt;br /&gt;It works fine on my lenovo T61p.&lt;br /&gt;&lt;br /&gt;Guijin Ding&lt;br /&gt;2009/4/24&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4323096950308185700?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4323096950308185700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4323096950308185700' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4323096950308185700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4323096950308185700'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2009/04/hda-sound-driver-for-my-t61p.html' title='The HDA sound driver for my T61p'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6961417331650329160</id><published>2009-02-11T21:24:00.002+08:00</published><updated>2009-02-11T21:31:55.801+08:00</updated><title type='text'>Source code has been put on google code</title><content type='html'>Sorry for so many days no updates.  That should be a good news for some ones, I have put the code on google code.&lt;br /&gt;&lt;br /&gt;svn checkout http://82566mm-osx-driver.googlecode.com/svn/trunk/ 82566mm-osx-driver-read-only&lt;br /&gt;&lt;br /&gt;  Welcome any comments or any improvements. You can email to me to say what you want to change and attach the change result source code file. I will merge and check in the code and share in google code.&lt;br /&gt;&lt;br /&gt;  If anyone who want contribute on this driver, it is welcomed and I will update the google code project to make sure you get the check-in permission.&lt;br /&gt;&lt;br /&gt;Guijin Ding&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6961417331650329160?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6961417331650329160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6961417331650329160' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6961417331650329160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6961417331650329160'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2009/02/source-code-has-been-put-on-google-code.html' title='Source code has been put on google code'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-896097533727261094</id><published>2008-11-06T19:15:00.002+08:00</published><updated>2008-11-06T19:17:51.297+08:00</updated><title type='text'>Intel 82566MM -- Link is broken</title><content type='html'>try this, &lt;a href="http://www.imconverter.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; Intel82566MM.kext.tar.gz &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-896097533727261094?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/896097533727261094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=896097533727261094' title='281 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/896097533727261094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/896097533727261094'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/11/intel-82566mm-link-is-broken.html' title='Intel 82566MM -- Link is broken'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>281</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-1290238402565562482</id><published>2008-10-29T22:05:00.004+08:00</published><updated>2008-10-29T22:22:26.531+08:00</updated><title type='text'>video converter for Mac OS X</title><content type='html'>The video converter for Mac OS X has been almost done. In a few weeks I will public it. And this software wrapper ffmpeg to do media content encode/decode.&lt;br /&gt;&lt;br /&gt;This software use Cocoa and Apple undocumented API -- cover flow.&lt;br /&gt;&lt;br /&gt;Check out the screenshot:&lt;br /&gt;&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/9O1S_UiE_BZNl6gdMZPdIQ"&gt;&lt;img src="http://lh3.ggpht.com/dingguijin/SQhxLHKGIaI/AAAAAAAAAZ0/3i2ccXNEFg4/s400/Picture%201.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;Sender &lt;a href="http://picasaweb.google.com/dingguijin/VideoConverterForMacOSX"&gt;video converter for Mac OS X&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-1290238402565562482?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/1290238402565562482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=1290238402565562482' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1290238402565562482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1290238402565562482'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/video-converter-for-mac-os-x.html' title='video converter for Mac OS X'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/dingguijin/SQhxLHKGIaI/AAAAAAAAAZ0/3i2ccXNEFg4/s72-c/Picture%201.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7950498944463362847</id><published>2008-10-15T07:57:00.000+08:00</published><updated>2008-10-15T07:58:02.659+08:00</updated><title type='text'>Updated Intel82566MM driver - Oct. 15th 2008</title><content type='html'>To support netstats in the driver.&lt;br /&gt;&lt;br /&gt;Download the latest &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; kext package. &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7950498944463362847?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7950498944463362847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7950498944463362847' title='30 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7950498944463362847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7950498944463362847'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/updated-intel82566mm-driver-oct-15th.html' title='Updated Intel82566MM driver - Oct. 15th 2008'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>30</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8076854357325331024</id><published>2008-10-14T20:01:00.002+08:00</published><updated>2008-10-14T20:06:26.272+08:00</updated><title type='text'>Update Intel82566MM driver - Oct. 14 2008</title><content type='html'>Update the Intel82566MM driver for Leopard (at lease 10.5.2).&lt;br /&gt;To avoid some potential catch the sharing interrupt that does not belong to itself.&lt;br /&gt;&lt;br /&gt;Maybe it is the root cause that sb who has the Intel HDA audio does not work well after installing the Intel82566MM driver. :-)&lt;br /&gt;&lt;br /&gt;Download the latest &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; kext package. &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8076854357325331024?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8076854357325331024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8076854357325331024' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8076854357325331024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8076854357325331024'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/update-intel82566mm-driver-oct-14-2008.html' title='Update Intel82566MM driver - Oct. 14 2008'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4445797609306984380</id><published>2008-10-09T17:34:00.002+08:00</published><updated>2008-10-09T17:44:47.743+08:00</updated><title type='text'>For nVidia Quadro 570m support in Mac OS X</title><content type='html'>I have tried, tried. It is too hard and no clue so far.&lt;br /&gt;The same as your feeling, I want to enable the QE/CI in my Leopard on T61p all the way. It is too hard and no clue.&lt;br /&gt;I can share the research information on the hacking procgress. Maybe it is a never win fight.&lt;br /&gt;&lt;br /&gt;A site focused on nVidia card reverse engineering.&lt;br /&gt;http://nouveau.freedesktop.org/wiki/&lt;br /&gt;&lt;br /&gt;Apple resouces but not very clearly to say how to write a Graphics driver to support QE/CI. But IOGraphics is open source. (unfortunately it can not be compiled by my xcode, need change somthing?)&lt;br /&gt;http://developer.apple.com/documentation/Darwin/Reference/IOKit/IOGraphicsLib/CompositePage.html&lt;br /&gt;http://developer.apple.com/documentation/Darwin/Conceptual/KEXTConcept/KEXTConcept.pdf&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4445797609306984380?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4445797609306984380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4445797609306984380' title='28 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4445797609306984380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4445797609306984380'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/for-nvidia-quadro-570m-support-in-mac.html' title='For nVidia Quadro 570m support in Mac OS X'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>28</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-570601693879743462</id><published>2008-10-06T10:44:00.004+08:00</published><updated>2008-10-06T10:53:44.655+08:00</updated><title type='text'>Updated Intel8255MM Mac OSX driver - 10/6/2008</title><content type='html'>Please download from here &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz. &lt;/a&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Update to set the unknown ethernet device to ich8 serial by default.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-570601693879743462?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/570601693879743462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=570601693879743462' title='27 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/570601693879743462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/570601693879743462'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/updated-intel8255mm-mac-osx-driver.html' title='Updated Intel8255MM Mac OSX driver - 10/6/2008'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>27</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7910888267350555141</id><published>2008-10-03T19:25:00.002+08:00</published><updated>2008-10-03T19:37:27.843+08:00</updated><title type='text'>Update Intel82566MM intend to support all kinds of e1000e ethernet card</title><content type='html'>Update the code and wish to support all kinds of Ehternet chips of Intel E1000E. Hope it can work.&lt;br /&gt;&lt;br /&gt;As usual, the &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz"&gt;package&lt;/a&gt; include the source code and precompiled kext.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7910888267350555141?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7910888267350555141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7910888267350555141' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7910888267350555141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7910888267350555141'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/update-intel82566mm-intend-to-support.html' title='Update Intel82566MM intend to support all kinds of e1000e ethernet card'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6108639924368073235</id><published>2008-10-03T07:39:00.002+08:00</published><updated>2008-10-03T07:47:47.141+08:00</updated><title type='text'>Thanks for your inspiration</title><content type='html'>I have added a donation button ... to keep the working going on. To support more intel e1000 PCIe ethernet cards on Leopard those e1000e (a project of sourceforge) supported.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6108639924368073235?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6108639924368073235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6108639924368073235' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6108639924368073235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6108639924368073235'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/thanks-for-your-inspiration.html' title='Thanks for your inspiration'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-259962294615523807</id><published>2008-10-01T20:56:00.003+08:00</published><updated>2008-10-01T21:04:25.090+08:00</updated><title type='text'>Intel 82566MM Mac OS X (Leopard) driver works today</title><content type='html'>Eventually, it works. This message coming from my Safari. And source code and kext binary still in there -- &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz"&gt;http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz&lt;/a&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;There are still some features need to be added (Power manager, VLAN support, checksum offloading, TCP segments support). But those are not critical.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-259962294615523807?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/259962294615523807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=259962294615523807' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/259962294615523807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/259962294615523807'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/10/intel-82566mm-mac-os-x-leopard-driver.html' title='Intel 82566MM Mac OS X (Leopard) driver works today'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4201673936683566118</id><published>2008-09-27T10:09:00.003+08:00</published><updated>2008-09-27T11:21:09.988+08:00</updated><title type='text'>Intel 82566MM -- Mac OS X driver that can ping another host.</title><content type='html'>Ping crash fix. new issue present -&gt; many incoming packets without EOP (End of Packet) flag.&lt;br /&gt;&lt;br /&gt;Fixing... Sorry for the progress :-)&lt;br /&gt;&lt;br /&gt;The latest &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz"&gt; source code and kext binary &lt;/a&gt; has been updated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4201673936683566118?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4201673936683566118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4201673936683566118' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4201673936683566118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4201673936683566118'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-mac-os-x-driver-that-can_27.html' title='Intel 82566MM -- Mac OS X driver that can ping another host.'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-3349622662727762494</id><published>2008-09-24T23:35:00.002+08:00</published><updated>2008-09-24T23:37:17.727+08:00</updated><title type='text'>Intel 82566MM -- Mac OS X driver that can ping another host.</title><content type='html'>Oh, that is great. But there is still possible crash.&lt;br /&gt;&lt;br /&gt;Try this version and feel my progress.^_^ &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz"&gt; source code &lt;/a&gt; under GPL&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-3349622662727762494?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/3349622662727762494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=3349622662727762494' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3349622662727762494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3349622662727762494'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-mac-os-x-driver-that-can.html' title='Intel 82566MM -- Mac OS X driver that can ping another host.'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4260619931152556585</id><published>2008-09-21T14:40:00.005+08:00</published><updated>2008-09-21T22:02:03.735+08:00</updated><title type='text'>Intel 82566MM -- Mac OS X driver with source code (cable plugin-&gt; active,  caple unplug-&gt; inactive)</title><content type='html'>Now watchdog can work. and you can plugin/unplugin the cable and see the "ifconfig" simultaneously.&lt;br /&gt; &lt;br /&gt;&lt;br&gt;&lt;br /&gt;Try this version and feel my progress. &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; kext download &lt;/a&gt; and &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.tar.gz"&gt; source code &lt;/a&gt; under GPL.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Now the driver still can not work for sending/receiving. Any comments is welcome. ^_^&lt;br /&gt;&lt;br&gt;&lt;br /&gt;su to root user and excute&lt;br /&gt;&lt;br&gt;&lt;br /&gt;cd /tmp&lt;br /&gt;&lt;br&gt;&lt;br /&gt;tar zxvf xxxx/Intel82566MM.tar.gz&lt;br /&gt;&lt;br&gt;&lt;br /&gt;ls -l (check Intel82566MM.kext has correct user:group that should be root:wheel)&lt;br /&gt;&lt;br&gt;&lt;br /&gt;kextload Intel82566MM.kext&lt;br /&gt;&lt;br&gt;&lt;br /&gt;...... (ifconfig or other Mac OS X network config tools)&lt;br /&gt;&lt;br&gt;&lt;br /&gt;kextunload Intel82566MM.kext&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;WARNING and DISCLAIM:&lt;/strong&gt; The driver is only suit for Lenovo T61p. Using or Testing the driver may crash your system. You should make sure you have backup and made your data safty. And you take the total risk if you install/running this driver.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4260619931152556585?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4260619931152556585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4260619931152556585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4260619931152556585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4260619931152556585'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-mac-os-x-driver-cable.html' title='Intel 82566MM -- Mac OS X driver with source code (cable plugin-&gt; active,  caple unplug-&gt; inactive)'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-1470764155797220067</id><published>2008-09-20T22:19:00.004+08:00</published><updated>2008-09-20T22:37:42.464+08:00</updated><title type='text'>Intel 82566MM -- Mac OS X driver init and start done.</title><content type='html'>After a couple of days and many reboots. the init and start of the driver for Intel82566MM on Mac OS X almost done.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Now I am working on the enable and disable interface of the driver.&lt;br /&gt;So far the driver can get the mac address of the Intel82566MM ethernet card and could be configured by ifconfig or Mac OS X setup tool.&lt;br /&gt;&lt;br&gt;&lt;br /&gt;A watchdog timer is running and check the link down and up. (Actually it works not very well. I am fixing it.)&lt;br /&gt;&lt;br&gt;&lt;br /&gt;Try this version and feel my progress. &lt;a href="http://www.tootoosoft.com/intel82566mm/Intel82566MM.kext.tar.gz"&gt; download &lt;/a&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;su to root user and excute&lt;br /&gt;&lt;br&gt;&lt;br /&gt;cd /tmp&lt;br /&gt;&lt;br&gt;&lt;br /&gt;tar zxvf xxxx/Intel82566MM.tar.gz&lt;br /&gt;&lt;br&gt;&lt;br /&gt;ls -l (check Intel82566MM.kext has correct user:group that should be root:wheel)&lt;br /&gt;&lt;br&gt;&lt;br /&gt;kextload Intel82566MM.kext&lt;br /&gt;&lt;br&gt;&lt;br /&gt;...... (ifconfig or other Mac OS X network config tools)&lt;br /&gt;&lt;br&gt;&lt;br /&gt;kextunload Intel82566MM.kext&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;WARNING and DISCLAIM:&lt;/strong&gt; The driver is only suit for Lenovo T61p. Using or Testing the driver may crash your system. You should make sure you have backup and made your data safty. And you take the total risk if you install/running this driver.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-1470764155797220067?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/1470764155797220067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=1470764155797220067' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1470764155797220067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1470764155797220067'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-mac-os-x-driver-init-and.html' title='Intel 82566MM -- Mac OS X driver init and start done.'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-2981655543084040466</id><published>2008-09-03T23:57:00.002+08:00</published><updated>2008-09-04T00:02:53.809+08:00</updated><title type='text'>How to write Mac OS X device driver without Xcode -- Makefile to create Mac OS X device driver</title><content type='html'>I got a Makefile to write my ethernet device driver.&lt;br /&gt;&lt;br /&gt;CC = /Developer/usr/bin/gcc-4.0 &lt;br /&gt;CXX = /Developer/usr/bin/g++-4.0 &lt;br /&gt;SYSROOT = /Developer/SDKs/MacOSX10.5.sdk&lt;br /&gt;ARCHFLAGS = -arch i386 -isysroot ${SYSROOT} -mmacosx-version-min=10.5&lt;br /&gt;&lt;br /&gt;CXXFLAGS = -x c++ ${ARCHFLAGS} -fmessage-length=0 -pipe -nostdinc -fno-builtin \&lt;br /&gt; -Wno-trigraphs -fno-exceptions -fno-rtti -fcheck-new -fasm-blocks \&lt;br /&gt; -force_cpusubtype_ALL -static -msoft-float -Os -fno-common \&lt;br /&gt; -mkernel -finline -fno-keep-inline-functions -Wreturn-type \&lt;br /&gt; -Wunused-variable -DKERNEL -DKERNEL_PRIVATE -DDRIVER_PRIVATE -DAPPLE \&lt;br /&gt; -DNeXT -fapple-kext -gdwarf-2 \&lt;br /&gt; -I/System/Library/Frameworks/Kernel.framework/PrivateHeaders \&lt;br /&gt;        -I/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Kernel.framework/Headers \&lt;br /&gt; -I.&lt;br /&gt;&lt;br /&gt;CFLAGS = -x c ${ARCHFLAGS} -fmessage-length=0 -pipe -nostdinc -std=c99 -fno-builtin \&lt;br /&gt; -Wno-trigraphs -fasm-blocks -force_cpusubtype_ALL -static -msoft-float -Os -fno-common \&lt;br /&gt; -mkernel -finline -fno-keep-inline-functions -Wreturn-type -Wunused-variable \&lt;br /&gt; -DKERNEL -DKERNEL_PRIVATE -DDRIVER_PRIVATE -DAPPLE -DNeXT -gdwarf-2 \&lt;br /&gt; -I/System/Library/Frameworks/Kernel.framework/PrivateHeaders \&lt;br /&gt;        -I/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Kernel.framework/Headers \&lt;br /&gt; -I.&lt;br /&gt;&lt;br /&gt;CXXLDFLAGS = -lcpp_kext -static -nostdlib -r -lkmodc++ &lt;br /&gt;CLDFLAGS = -lkmod -lcc_kext&lt;br /&gt;&lt;br /&gt;COBJS = Intel82566MM_info.o&lt;br /&gt;CXXOBJS = Intel82566MM.o hw.o nvm.o fc.o mac.o dhcp.o&lt;br /&gt;&lt;br /&gt;DRIVER_IMAGE = Intel82566MM&lt;br /&gt;all: ${DRIVER_IMAGE}&lt;br /&gt;&lt;br /&gt;%.o: %.cpp&lt;br /&gt; ${CC} -c ${CXXFLAGS} $&lt; -o $@&lt;br /&gt;%.o: %.c&lt;br /&gt; ${CC} -c ${CFLAGS} $&lt; -o $@&lt;br /&gt;&lt;br /&gt;${DRIVER_IMAGE}: ${COBJS} ${CXXOBJS}&lt;br /&gt; ${CXX} ${ARCHFLAGS} ${CXXOBJS} ${CXXLDFLAGS} ${COBJS} ${CLDFLAGS} -o ${DRIVER_IMAGE} &lt;br /&gt;&lt;br /&gt;clean:&lt;br /&gt; rm -f *.o ${DRIVER_IMAGE}&lt;br /&gt;&lt;br /&gt;Note: the xxx_info.c is the driver entry fot IOkit device driver. For my driver it is:&lt;br /&gt;&lt;br /&gt;#include &lt;mach/mach_types.h&gt;&lt;br /&gt; &lt;br /&gt;extern kern_return_t _start(kmod_info_t *ki, void *data);&lt;br /&gt;extern kern_return_t _stop(kmod_info_t *ki, void *data);&lt;br /&gt; &lt;br /&gt;KMOD_EXPLICIT_DECL(com.tootoosoft.driver.Intel82566MM, "1.0.0d1", _start, _stop)&lt;br /&gt;__private_extern__ kmod_start_func_t *_realmain = 0;&lt;br /&gt;__private_extern__ kmod_stop_func_t *_antimain = 0;&lt;br /&gt;__private_extern__ int _kext_apple_cc = __APPLE_CC__ ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So you choose what you like to create the device driver.&lt;br /&gt;Emacs or VIM.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-2981655543084040466?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/2981655543084040466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=2981655543084040466' title='57 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2981655543084040466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2981655543084040466'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/how-to-write-mac-os-x-device-driver.html' title='How to write Mac OS X device driver without Xcode -- Makefile to create Mac OS X device driver'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>57</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6409300469548381744</id><published>2008-09-03T06:58:00.002+08:00</published><updated>2008-09-03T07:01:34.788+08:00</updated><title type='text'>Oh kextunload ......</title><content type='html'>If you over write free() of IOEthernentController, you must call IOEthernetController::free() in your free() method. Otherwise you never unload this kext unless reboot your Mac ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6409300469548381744?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6409300469548381744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6409300469548381744' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6409300469548381744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6409300469548381744'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/oh-kextunload.html' title='Oh kextunload ......'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6844521812131797434</id><published>2008-09-02T14:58:00.001+08:00</published><updated>2008-09-02T14:59:12.280+08:00</updated><title type='text'>Intel 82566MM -- How to access EEPROM/NVM?</title><content type='html'>The Ethernet controller provides two different methods for software access to the EEPROM. It can either use the built-in controller to read the EEPROM or access the EEPROM directly using the EEPROM’s 4-wire interface.&lt;br /&gt;&lt;br /&gt;Software can use the EEPROM Read register (EERD) to cause the Ethernet controller to read a word from the EEPROM that the software can then use. To do this, software writes the address to read into the Read Address field (EERD.ADDR; bits 15:2) and simultaneously writes a 1b to the Start Read bit (EERD.START; bit 0). The Ethernet controller then reads the word from the EEPROM, sets the Read Done bit (EERD.DONE; bit 1), and puts the data in the Read Data field (EERD.DATA; bits 31:16). Software can poll the EEPROM Read register until it sees the Read Done bit set, then use the data from the Read Data field. Any words read this way are not written to the Ethernet controller’s internal registers. &lt;br /&gt;&lt;br /&gt;Software can also directly access the EEPROM’s 4-wire interface through the EEPROM/Flash Control register (EEC). It can use this for reads, writes, or other EEPROM operations. &lt;br /&gt;&lt;br /&gt;To directly access the EEPROM, software should follow these steps:&lt;br /&gt;1. Write a 1b to the EEPROM Request bit (EEC.EE_REQ; bit 6).&lt;br /&gt;2. Read the EEPROM Grant bit (EEC.EE_GNT; bit 7) until it becomes 1b. It remains 0b as long as the hardware is accessing the EEPROM. Write or read the EEPROM using the direct access to the 4-wire interface as defined in the EEPROM/Flash Control &amp; Data register (EEC). The exact protocol used depends on the EEPROM placed on the board and can be found in the appropriate datasheet.&lt;br /&gt;4. Write a 0b to the EEPROM Request bit (EEC.EE_REQ; bit 6).&lt;br /&gt;Finally, software can cause the Ethernet controller to re-read part of the hardware accessed fields of the EEPROM (setting the Ethernet controller’s internal registers appropriately) by writing a 1b to the EEPROM Reset bit of the Extended Device Control Register (CTRL_EXT.EE_RST; bit 13).&lt;br /&gt;&lt;br /&gt;In Linux e1000e driver, it used the second method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6844521812131797434?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6844521812131797434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6844521812131797434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6844521812131797434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6844521812131797434'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-how-to-access-eepromnvm.html' title='Intel 82566MM -- How to access EEPROM/NVM?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8820622152218736589</id><published>2008-09-02T11:16:00.001+08:00</published><updated>2008-09-02T11:18:25.570+08:00</updated><title type='text'>Mac OS X Device Driver -- what is work loop?</title><content type='html'>Tired to understanding the Linux Intel e1000e driver. Change my mind to Mac OS X and have a break.&lt;br /&gt;&lt;br /&gt;Interrupt service threads are the standard way of handling interrupts in Mac OS X device drivers, though they often go by another name, the work loop. A work loop is a thread whose sole purpose is to wait for an event such as an interrupt to occur, then call an appropriate handler function to do the actual work of processing the interrupt—checking the result, copying data, and so on. This activity occurs in a kernel thread. The kernel thread does not receive the actual interrupt, however. A low-level interrupt handler receives the primary interrupt. It then generates a software interrupt known as a secondary interrupt. The interrupt service thread receives that secondary software interrupt. Thus, routines running in an interrupt service thread do not have to obey the same rules as an actual interrupt handler; they can block, call IOLog, and so on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8820622152218736589?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8820622152218736589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8820622152218736589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8820622152218736589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8820622152218736589'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/mac-os-x-device-driver-what-is-work.html' title='Mac OS X Device Driver -- what is work loop?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-3058024451088182353</id><published>2008-09-02T10:29:00.001+08:00</published><updated>2008-09-02T10:31:15.007+08:00</updated><title type='text'>PCI Matching Policy in Mac OS X</title><content type='html'>PCI Matching&lt;br /&gt;&lt;br /&gt;PCI device drivers can base their property matching on the PCI configuration space registers for vendor and device ID (offsets 0x00 and 0x02), subsystem vendor and device ID (offsets 0x2C and 0x2E), and class code (offset 0x09). Other registers, such as revision ID and header type, are not available in property matching and must be examined by the probe method.&lt;br /&gt;&lt;br /&gt;The PCI matching dictionary keys are:&lt;br /&gt;&lt;br /&gt;IOPCIMatch: Matches against the primary vendor/device ID registers or the subsystem&lt;br /&gt;vendor/device ID registers. The primary IDs are checked first; if either of&lt;br /&gt;these doesn’t match then the subsystem IDs are checked.&lt;br /&gt;IOPCIPrimaryMatch: Matches only against the primary vendor/device ID registers.&lt;br /&gt;IOPCISecondaryMatch: Matches only against the subsystem vendor/device ID registers.&lt;br /&gt;IOPCIClassMatch: Matches against the class code register.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-3058024451088182353?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/3058024451088182353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=3058024451088182353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3058024451088182353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3058024451088182353'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/pci-matching-policy-in-mac-os-x.html' title='PCI Matching Policy in Mac OS X'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8710703412850614395</id><published>2008-09-02T10:12:00.002+08:00</published><updated>2008-09-02T10:15:32.942+08:00</updated><title type='text'>Oh PBA is another PBA.</title><content type='html'>PBA for OEM number.&lt;br /&gt;PBA (Packet Buffer Allocation).&lt;br /&gt;&lt;br /&gt;Two PBA in the chip, a little confusing.&lt;br /&gt;&lt;br /&gt;PBA (01000h; R/W)&lt;br /&gt;This register sets the on-chip receive and transmit storage allocation ratio. The receive allocation value is read/write for the lower six bits. The transmit allocation is read-only and is calculated based on PBA.RXA. The partitioning size is 1 KB.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8710703412850614395?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8710703412850614395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8710703412850614395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8710703412850614395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8710703412850614395'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/oh-pba-is-another-pba.html' title='Oh PBA is another PBA.'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-3653650437282031447</id><published>2008-09-02T09:46:00.002+08:00</published><updated>2008-09-02T09:49:09.004+08:00</updated><title type='text'>What is NAPI?</title><content type='html'>To make thing as simple as possible. I try to disable the NAPI mode. It may cause some performance lost.&lt;br /&gt;&lt;br /&gt;But how NAPI. The folling two links are very good start points.&lt;br /&gt;&lt;br /&gt;http://lwn.net/Articles/30107/&lt;br /&gt;http://www.linuxfoundation.org/en/Net:NAPI&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-3653650437282031447?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/3653650437282031447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=3653650437282031447' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3653650437282031447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3653650437282031447'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/what-is-napi.html' title='What is NAPI?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7705157907638821313</id><published>2008-09-02T07:11:00.001+08:00</published><updated>2008-09-02T07:13:18.193+08:00</updated><title type='text'>Intel 82566MM -- what type of interrupt shold be masked?</title><content type='html'>That comes the definition of e1000e source of Linux kerenel.&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * This defines the bits that are set in the Interrupt Mask&lt;br /&gt; * Set/Read Register.  Each bit is documented below:&lt;br /&gt; *   o RXT0   = Receiver Timer Interrupt (ring 0)&lt;br /&gt; *   o TXDW   = Transmit Descriptor Written Back&lt;br /&gt; *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)&lt;br /&gt; *   o RXSEQ  = Receive Sequence Error&lt;br /&gt; *   o LSC    = Link Status Change&lt;br /&gt; */&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7705157907638821313?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7705157907638821313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7705157907638821313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7705157907638821313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7705157907638821313'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-what-type-of-interrupt.html' title='Intel 82566MM -- what type of interrupt shold be masked?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4533089131702927620</id><published>2008-09-01T21:50:00.001+08:00</published><updated>2008-09-01T21:52:41.298+08:00</updated><title type='text'>Intel 82566MM -- What is PBA?</title><content type='html'>The nine-digit Printed Board Assembly (PBA) number, used for Intel manufactured adapter cards, is stored in a four-byte field. The dash itself is not stored, neither is the first digit of the 3-digit suffix, as it will always be 0b for the affected products. Note that through the course of&lt;br /&gt;hardware ECOs, the suffix field (byte 4) is incremented. The purpose of this information is to allow Customer Support (or any user) to identify the exact revision level of a product. Network driver software should not rely on this field to identify the product or its capabilities.&lt;br /&gt;&lt;br /&gt;Only Intel engineer to surstaining ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4533089131702927620?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4533089131702927620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4533089131702927620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4533089131702927620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4533089131702927620'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/intel-82566mm-what-is-pba.html' title='Intel 82566MM -- What is PBA?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-2416480649074215172</id><published>2008-09-01T12:55:00.002+08:00</published><updated>2008-09-01T12:58:44.689+08:00</updated><title type='text'>What is Intel AMT in 82566MM?</title><content type='html'>The Gigabite Ethernet Controller is integrated in ICH8.&lt;br /&gt;AMT is provided as well.&lt;br /&gt;&lt;br /&gt;But what is AMT?&lt;br /&gt;&lt;br /&gt;Intel® Active Management Technology (Intel®&lt;br /&gt;AMT) (Intel® ICH8DO and ICH8M-E Only))&lt;br /&gt;Intel Active Management Technology is a set of advanced manageability features&lt;br /&gt;developed as a direct result of IT customer feedback gained through Intel market&lt;br /&gt;research. Reducing the Total Cost of Ownership (TCO) through improved asset tracking,&lt;br /&gt;remote manageability, and fewer desk-side visits were identified as key IT priorities.&lt;br /&gt;Intel AMT extends the capabilities of existing management solutions by making the&lt;br /&gt;asset information, remote diagnostics, recovery and contain capabilities always&lt;br /&gt;available, or Out of Band (OOB), even when the system is in a low-power “off” state or&lt;br /&gt;the OS is hung.&lt;br /&gt;Another technology feature of Intel Active Technology is System Defense. System&lt;br /&gt;Defense is a Intel AMT feature that is used to stop the propagation of worms and&lt;br /&gt;viruses. Programmable packet filters in the integrated LAN Controller are used to&lt;br /&gt;accomplish this. These filters inspect all incoming and all outgoing packets and decide&lt;br /&gt;whether to block or pass the packets as configured. There is no indication to the host&lt;br /&gt;that a packet has been blocked or accepted.&lt;br /&gt;The logic can be used to accept or block reception to host or transmission to network&lt;br /&gt;paths. Additionally, counter logic can be used to count the number or filter matches for&lt;br /&gt;a given filter. This feature allows for statistical sampling of connections as well as rate&lt;br /&gt;limiting of connections.&lt;br /&gt;&lt;br /&gt;What features does it provided?&lt;br /&gt;• E-Asset Tag&lt;br /&gt;• OOB HW and SW Inventory Logs&lt;br /&gt;• OOB Alerts&lt;br /&gt;• IDE Redirect&lt;br /&gt;• Serial over LAN for Remote Control&lt;br /&gt;• Remote Diagnostics Execution&lt;br /&gt;• OS Lock-Up Alert&lt;br /&gt;• OS Repair&lt;br /&gt;• Remote BIOS Recovery and Update&lt;br /&gt;&lt;br /&gt;I would like to disable the feature in my driver for Mac OS X.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-2416480649074215172?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/2416480649074215172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=2416480649074215172' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2416480649074215172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2416480649074215172'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/09/what-is-intel-amt-in-82566mm.html' title='What is Intel AMT in 82566MM?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7011057161772598683</id><published>2008-08-31T22:31:00.002+08:00</published><updated>2008-08-31T22:38:18.869+08:00</updated><title type='text'>Understanding Intel 82566MM driver source on Linux</title><content type='html'>Understanding Intel 82566MM driver source on Linux. That is the first step to port it to Mac OS X.&lt;br /&gt;&lt;br /&gt;It is really not a one-day-project.&lt;br /&gt;&lt;br /&gt;Today after a few hours, I got the basic infrustucture of the e1000e source and delete many code those are irrelvant with the 82566MM... (ethtool, param parser, 82571, msi interrupt, NAPI support, kcompat and so on totally been removed).&lt;br /&gt;&lt;br /&gt;And the left code still can work on my T61p. &lt;br /&gt;&lt;br /&gt;The understanding work still need go on ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7011057161772598683?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7011057161772598683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7011057161772598683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7011057161772598683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7011057161772598683'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/08/understanding-intel-82566mm-driver.html' title='Understanding Intel 82566MM driver source on Linux'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-4035612640737071996</id><published>2008-08-31T09:33:00.001+08:00</published><updated>2008-08-31T09:34:52.746+08:00</updated><title type='text'>Leopard 82566MM driver - Apple Intel 82557 Driver sample</title><content type='html'>I got the Apple Intel 82557 driver source from Darwin Open Source project.&lt;br /&gt;&lt;br /&gt;So far, I believe everything is ready to develop my 82566MM driver on Mac OS X.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-4035612640737071996?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/4035612640737071996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=4035612640737071996' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4035612640737071996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/4035612640737071996'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/08/leopard-82566mm-driver-apple-intel.html' title='Leopard 82566MM driver - Apple Intel 82557 Driver sample'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8332399306689460474</id><published>2008-08-31T09:30:00.002+08:00</published><updated>2008-08-31T09:33:07.067+08:00</updated><title type='text'>Leopard 82566MM driver - Mac resource</title><content type='html'>How to write a KEXT on Mac OS X.&lt;br /&gt;How to write a Device Driver (IOKit) on Mac OS X.&lt;br /&gt;How to write a Network device driver on Mac OS X.&lt;br /&gt;&lt;br /&gt;These document could be download from Apple Developer Connection.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8332399306689460474?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8332399306689460474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8332399306689460474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8332399306689460474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8332399306689460474'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/08/leopard-82566mm-driver-mac-resource.html' title='Leopard 82566MM driver - Mac resource'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-3802793914790500886</id><published>2008-08-31T09:28:00.002+08:00</published><updated>2008-08-31T09:30:32.519+08:00</updated><title type='text'>Leopard 82566MM driver - Linux resource</title><content type='html'>Linux resource&lt;br /&gt;&lt;br /&gt;The sourceforge project e1000 is a good place for Linux e1000 driver.&lt;br /&gt;&lt;br /&gt;Linux 2.6.22.3 has integrated the PCIe e1000 driver in its net driver (e1000 and e1000e).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-3802793914790500886?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/3802793914790500886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=3802793914790500886' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3802793914790500886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3802793914790500886'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/08/leopard-82566mm-driver-linux-resource.html' title='Leopard 82566MM driver - Linux resource'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-2533520498957373238</id><published>2008-08-31T09:20:00.003+08:00</published><updated>2008-08-31T09:28:09.810+08:00</updated><title type='text'>Leopard 82566MM driver - I decided port e1000/e1000e network card driver to my hackintosh</title><content type='html'>I decided port e1000/e1000e network card driver to my hackintosh&lt;br /&gt;&lt;br /&gt;I have installed Leopard on my laptop (Lenovo T61p). But the Intel 82566MM is not drived by the hackintosh. &lt;br /&gt;&lt;br /&gt;It is 2 months that I have been waiting the open community people to resolve this problem. But it really frustrate me.&lt;br /&gt;&lt;br /&gt;So I decided work on it.&lt;br /&gt;&lt;br /&gt;The day is the start point. It is August 31 2008.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-2533520498957373238?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/2533520498957373238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=2533520498957373238' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2533520498957373238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2533520498957373238'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2008/08/leopard-82566mm-driver-i-decided-port.html' title='Leopard 82566MM driver - I decided port e1000/e1000e network card driver to my hackintosh'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-1775958851252380634</id><published>2007-05-31T15:31:00.000+08:00</published><updated>2007-05-31T15:42:47.991+08:00</updated><title type='text'>100阶台阶的走法</title><content type='html'>100阶台阶，每次走1或者2阶，共有多少种走法？&lt;br /&gt;&lt;br /&gt;考虑在99处走一个1到达终点，也可以考虑是在98处选择两个走。 那么100阶台阶上来的可能只有两类，一类是从99过来的1，一类是从98过来的2。所以100阶台阶的走法就很明显了是 99阶 于 98阶的和。&lt;br /&gt;&lt;br /&gt;那么如果可能走 1， 2， 3个台阶呢，应该也可以推算出来了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-1775958851252380634?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/1775958851252380634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=1775958851252380634' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1775958851252380634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1775958851252380634'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/05/100.html' title='100阶台阶的走法'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-1017853088262451148</id><published>2007-05-16T12:17:00.000+08:00</published><updated>2007-05-16T12:19:00.187+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xlib XImage'/><title type='text'>写个Xlib的BMP文件显示程序</title><content type='html'>&lt;span class="post"&gt;项目中有这个需要四处 找可用的 信息。终于从一个叫IV的程序源码得到了最后的解决方法。&lt;br /&gt;&lt;br /&gt;整个遇到的问题主要有&lt;br /&gt;1 bmp的数据结构在GCC下被缺省4字节对齐，需要在bmp file info 和 bmp info header struct定义最后加上 __attribute__((packed)),值得注意的是不要放到typedef 一行中，这个问题困扰了我一下.&lt;br /&gt;&lt;br /&gt;2 Xlib中显示有颜色的图像需要根据当前链接的DISPLAY的colormap有关系，这是可以理解的，就是比较麻烦，对于不同的Xserver你的显示程序可能要写成不一样 .&lt;br /&gt;&lt;br /&gt;3 如果要想动态获得当前DISPLAY提供的像素颜色，那么制作一个XImage的时间会不可接受（对于超过 256彩色的 图像）&lt;br /&gt;&lt;br /&gt;这是我在做的过程中发现的问题。&lt;br /&gt;&lt;br /&gt;第一个问题解决的数据结构定义：&lt;br /&gt;&lt;br /&gt;typedef unsigned short int WORD;&lt;br /&gt;typedef unsigned int DWORD;&lt;br /&gt;typedef int LONG;&lt;br /&gt;&lt;br /&gt;struct tagRGBQUAD {&lt;br /&gt;       unsigned char rgbBlue;&lt;br /&gt;       unsigned char rgbGreen;&lt;br /&gt;       unsigned char rgbRed;&lt;br /&gt;       unsigned char rgbReserved;&lt;br /&gt;}__attribute__((packed));&lt;br /&gt;&lt;br /&gt;typedef struct tagRGBQUAD RGBQUAD;&lt;br /&gt;&lt;br /&gt;struct tagBITMAPFILEHEADER { &lt;br /&gt;       WORD    bfType; &lt;br /&gt;       DWORD   bfSize; &lt;br /&gt;       WORD    bfReserved1; &lt;br /&gt;       WORD    bfReserved2; &lt;br /&gt;       DWORD   bfOffBits; &lt;br /&gt;}__attribute__((packed));&lt;br /&gt;typedef struct tagBITMAPFILEHEADER BITMAPFILEHEADER;&lt;br /&gt;&lt;br /&gt;struct tagBITMAPINFOHEADER{&lt;br /&gt;       DWORD  biSize; &lt;br /&gt;       LONG   biWidth; &lt;br /&gt;       LONG   biHeight; &lt;br /&gt;       WORD   biPlanes; &lt;br /&gt;       WORD   biBitCount; &lt;br /&gt;       DWORD  biCompression; &lt;br /&gt;       DWORD  biSizeImage; &lt;br /&gt;       LONG   biXPelsPerMeter; &lt;br /&gt;       LONG   biYPelsPerMeter; &lt;br /&gt;       DWORD  biClrUsed; &lt;br /&gt;       DWORD  biClrImportant; &lt;br /&gt;}__attribute__((packed));&lt;br /&gt;&lt;br /&gt;typedef struct tagBITMAPINFOHEADER BITMAPINFOHEADER;&lt;br /&gt;&lt;br /&gt;//这些数据结构直接从MSDN从COPY，然后调整。&lt;br /&gt;&lt;br /&gt;//普通的显示图像的过程是这样的&lt;br /&gt;//打开DISPLAY， 创建WINDOW， 创建GC，打开 BMP 文件 读出结构信息和 BMP数据， 创建XIMAGE通过 BMP数据，标注关心的WINDOW事件 映射窗口 flush消息&lt;br /&gt;&lt;br /&gt;//开始窗口循环&lt;br /&gt;//在EXPOSE的事件上 显示XIMAGE数据&lt;br /&gt;//可以选择在KeyPress上把程序EXIT，我没有加， 如果想得到KeyCode，需要根据键盘字符找到 KeySym再在映射到keycode&lt;br /&gt;&lt;br /&gt;//程序如下&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;string.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;#include &lt;x11/xlib.h&gt;&lt;br /&gt;&lt;br /&gt;typedef unsigned short int WORD;&lt;br /&gt;typedef unsigned int DWORD;&lt;br /&gt;typedef int LONG;&lt;br /&gt;&lt;br /&gt;struct tagRGBQUAD {&lt;br /&gt;       unsigned char rgbBlue;&lt;br /&gt;       unsigned char rgbGreen;&lt;br /&gt;       unsigned char rgbRed;&lt;br /&gt;       unsigned char rgbReserved;&lt;br /&gt;}__attribute__((packed));&lt;br /&gt;&lt;br /&gt;typedef struct tagRGBQUAD RGBQUAD;&lt;br /&gt;&lt;br /&gt;struct tagBITMAPFILEHEADER { &lt;br /&gt;       WORD    bfType; &lt;br /&gt;       DWORD   bfSize; &lt;br /&gt;       WORD    bfReserved1; &lt;br /&gt;       WORD    bfReserved2; &lt;br /&gt;       DWORD   bfOffBits; &lt;br /&gt;}__attribute__((packed));&lt;br /&gt;typedef struct tagBITMAPFILEHEADER BITMAPFILEHEADER;&lt;br /&gt;&lt;br /&gt;struct tagBITMAPINFOHEADER{&lt;br /&gt;       DWORD  biSize; &lt;br /&gt;       LONG   biWidth; &lt;br /&gt;       LONG   biHeight; &lt;br /&gt;       WORD   biPlanes; &lt;br /&gt;       WORD   biBitCount; &lt;br /&gt;       DWORD  biCompression; &lt;br /&gt;       DWORD  biSizeImage; &lt;br /&gt;       LONG   biXPelsPerMeter; &lt;br /&gt;       LONG   biYPelsPerMeter; &lt;br /&gt;       DWORD  biClrUsed; &lt;br /&gt;       DWORD  biClrImportant; &lt;br /&gt;}__attribute__((packed));&lt;br /&gt;&lt;br /&gt;typedef struct tagBITMAPINFOHEADER BITMAPINFOHEADER;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int read_bmp_file(char* filename, unsigned char * const buffer,&lt;br /&gt;                 unsigned char** data, int* width, int* height, int* depth)&lt;br /&gt;{&lt;br /&gt;       FILE* fd;&lt;br /&gt;       int rt;&lt;br /&gt;       int channel;&lt;br /&gt;       unsigned char* bits;&lt;br /&gt;       &lt;br /&gt; BITMAPFILEHEADER    bmfh;&lt;br /&gt; BITMAPINFOHEADER    bmih;&lt;br /&gt;       &lt;br /&gt;       fd = fopen(filename, "rb");&lt;br /&gt; if(fd == NULL) {&lt;br /&gt;  printf("NO such file %s.\n", filename);&lt;br /&gt;  return -1;&lt;br /&gt; }&lt;br /&gt;       &lt;br /&gt; rt = fread(buffer, 1, 2*1024*1024, fd);&lt;br /&gt; printf("read image -&gt;%d.\n", rt);&lt;br /&gt;       fclose(fd);&lt;br /&gt;       &lt;br /&gt;       printf("sizeof(bmfh)-&gt;%d.\n", sizeof(bmfh));&lt;br /&gt;       printf("sizeof(bmih)-&gt;%d.\n", sizeof(bmih));&lt;br /&gt;       &lt;br /&gt; memcpy(&amp;bmfh, buffer, sizeof(bmfh));&lt;br /&gt; memcpy(&amp;bmih, buffer + sizeof(bmfh), sizeof(bmih));&lt;br /&gt; if(bmfh.bfType != 19778) {&lt;br /&gt;               return -1;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; bits = (unsigned char*) (buffer+bmfh.bfOffBits);&lt;br /&gt;       &lt;br /&gt;       channel = bmih.biBitCount/8;&lt;br /&gt; *depth = bmih.biBitCount;&lt;br /&gt; *width = bmih.biWidth;&lt;br /&gt; *height = bmih.biHeight;&lt;br /&gt;       &lt;br /&gt;       *data = bits;&lt;br /&gt;       printf("\tsize(%dx%d) channel:%d ---\n", *width, *height, channel);&lt;br /&gt;       return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int highbit(unsigned long ul)&lt;br /&gt;       &lt;br /&gt;{&lt;br /&gt;       int i;  unsigned long hb;&lt;br /&gt;       hb = 0x8000;  hb = (hb&lt;&lt;16);  /* hb = 0x80000000UL */&lt;br /&gt;       for (i=31; ((ul &amp; hb) == 0) &amp;amp;&amp; i&gt;=0;  i--, ul&lt;&lt;=1);&lt;br /&gt;       return i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;XImage* create_ximage(Display* dpy, unsigned char* data,&lt;br /&gt;                     int width, int height, int bdepth)&lt;br /&gt;{&lt;br /&gt; Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));&lt;br /&gt; int depth = DefaultDepth(dpy, DefaultScreen(dpy));&lt;br /&gt;       XImage* res;&lt;br /&gt;       int i, j;&lt;br /&gt;       unsigned char* idata;&lt;br /&gt;       &lt;br /&gt; res = XCreateImage(dpy, visual, depth, ZPixmap, 0 /*offset*/,&lt;br /&gt;                    NULL, width, height, 32, 0);&lt;br /&gt; if (res == NULL) {&lt;br /&gt;  return NULL;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;       idata = (unsigned char*)malloc(res-&gt;bytes_per_line*height);&lt;br /&gt;       res-&gt;data = idata;&lt;br /&gt;&lt;br /&gt;       {&lt;br /&gt;               unsigned long r, g, b, rmask, gmask, bmask, xcol;&lt;br /&gt;               int rshift, gshift, bshift, bperpix, bperline, border;&lt;br /&gt;               unsigned char *ip, *pp;&lt;br /&gt;               rmask = visual-&gt;red_mask;&lt;br /&gt;               gmask = visual-&gt;green_mask;&lt;br /&gt;               bmask = visual-&gt;blue_mask;&lt;br /&gt;               &lt;br /&gt;               rshift = 7 - highbit(rmask);&lt;br /&gt;               gshift = 7 - highbit(gmask);&lt;br /&gt;               bshift = 7 - highbit(bmask);&lt;br /&gt;               &lt;br /&gt;               bperline = res-&gt;bytes_per_line;&lt;br /&gt;               bperpix  = res-&gt;bits_per_pixel;&lt;br /&gt;               border   = res-&gt;byte_order;&lt;br /&gt;&lt;br /&gt;               pp = data;&lt;br /&gt;&lt;br /&gt;               for (i=0; i&lt;height; i++) {&lt;br /&gt;                       for (j=0; j&lt;width; j++) {&lt;br /&gt;                               b = *pp++;  g = *pp++;  r = *pp++;&lt;br /&gt;                               pp++;&lt;br /&gt;&lt;br /&gt;                               if (rshift&lt;0) r = r &lt;&lt; (-rshift);&lt;br /&gt;                               else r = r &gt;&gt; rshift;&lt;br /&gt;                               &lt;br /&gt;                               if (gshift&lt;0) g = g &lt;&lt; (-gshift);&lt;br /&gt;                               else g = g &gt;&gt; gshift;&lt;br /&gt;                               &lt;br /&gt;                               if (bshift&lt;0) b = b &lt;&lt; (-bshift);&lt;br /&gt;                               else b = b &gt;&gt; bshift;&lt;br /&gt;                               &lt;br /&gt;                               r = r &amp; rmask;&lt;br /&gt;                               g = g &amp; gmask;&lt;br /&gt;                               b = b &amp; bmask;&lt;br /&gt;                               &lt;br /&gt;                               xcol = r | g | b;&lt;br /&gt;&lt;br /&gt;                               &lt;br /&gt;                               ip = (idata+(height-1-i)*bperline+j*bperpix/8);&lt;br /&gt;                               if (bperpix == 32) {&lt;br /&gt;                                       if (border == MSBFirst) {&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;24) &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;16) &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                                       else {  /* LSBFirst */&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;16) &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;24) &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                               }&lt;br /&gt;                               &lt;br /&gt;                               else if (bperpix == 24) {&lt;br /&gt;                                       if (border == MSBFirst) {&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;16) &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                                       else {  /* LSBFirst */&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;16) &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                               }&lt;br /&gt;                               &lt;br /&gt;                               else if (bperpix == 16) {&lt;br /&gt;                                       if (border == MSBFirst) {&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                                       else {  /* LSBFirst */&lt;br /&gt;                                               *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                                               *ip++ = (xcol&gt;&gt;8)  &amp; 0xff;&lt;br /&gt;                                       }&lt;br /&gt;                               }&lt;br /&gt;                               &lt;br /&gt;                               else if (bperpix == 8) {&lt;br /&gt;                                       *ip++ =  xcol      &amp; 0xff;&lt;br /&gt;                               }&lt;br /&gt;                       }&lt;br /&gt;               }&lt;br /&gt;       }&lt;br /&gt; &lt;br /&gt;       &lt;br /&gt; return res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Window create_simple_window(Display* display, int width, int height, int x, int y)&lt;br /&gt;{&lt;br /&gt;       int screen_num = DefaultScreen(display);&lt;br /&gt;       int win_border_width = 2;&lt;br /&gt;       Window win;&lt;br /&gt;       &lt;br /&gt;       win = XCreateSimpleWindow(display, RootWindow(display, screen_num),&lt;br /&gt;                                 x, y, width, height, win_border_width,&lt;br /&gt;                                 BlackPixel(display, screen_num),&lt;br /&gt;                                 WhitePixel(display, screen_num));&lt;br /&gt;       &lt;br /&gt;       &lt;br /&gt;       return win;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;GC create_gc(Display* display, Window win, int reverse_video)&lt;br /&gt;{&lt;br /&gt;       GC gc;    /* handle of newly created GC.  */&lt;br /&gt;       unsigned long valuemask = 0;  /* which values in 'values' to  */&lt;br /&gt;       /* check when creating the GC.  */&lt;br /&gt;       XGCValues values;   /* initial values for the GC.   */&lt;br /&gt;       unsigned int line_width = 2;  /* line width for the GC.       */&lt;br /&gt;       int line_style = LineSolid;  /* style for lines drawing and  */&lt;br /&gt;       int cap_style = CapButt;  /* style of the line's edje and */&lt;br /&gt;       int join_style = JoinBevel;  /*  joined lines.  */&lt;br /&gt;       int screen_num = DefaultScreen(display);&lt;br /&gt;       &lt;br /&gt;       gc = XCreateGC(display, win, valuemask, &amp;values);&lt;br /&gt;       if (gc &lt; 0) {&lt;br /&gt;               printf("XCreateGC: \n");&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;       /* allocate foreground and background colors for this GC. */&lt;br /&gt;       if (reverse_video) {&lt;br /&gt;               XSetForeground(display, gc, WhitePixel(display, screen_num));&lt;br /&gt;               XSetBackground(display, gc, BlackPixel(display, screen_num));&lt;br /&gt;       }&lt;br /&gt;       else {&lt;br /&gt;               XSetForeground(display, gc, BlackPixel(display, screen_num));&lt;br /&gt;               XSetBackground(display, gc, WhitePixel(display, screen_num));&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;       /* define the style of lines that will be drawn using this GC. */&lt;br /&gt;       XSetLineAttributes(display, gc,&lt;br /&gt;                          line_width, line_style, cap_style, join_style);&lt;br /&gt;       &lt;br /&gt;       /* define the fill style for the GC. to be 'solid filling'. */&lt;br /&gt;       XSetFillStyle(display, gc, FillSolid);&lt;br /&gt;       &lt;br /&gt;       return gc;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int place_graphics(Display* display,&lt;br /&gt;                  Window win, GC gc,&lt;br /&gt;                  XImage* img,&lt;br /&gt;                  unsigned int width,&lt;br /&gt;                  unsigned int height)&lt;br /&gt;{&lt;br /&gt;       XPutImage(display, win, gc, img, 0, 0, 0, 0, width, height); &lt;br /&gt;       return 0;&lt;br /&gt;       &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int show_bmp_data(unsigned char* bmpdata, int bwidth, int bheight, int bdepth)&lt;br /&gt;{&lt;br /&gt;       Display* display; &lt;br /&gt;       int screen_num;  &lt;br /&gt;       Window win;  &lt;br /&gt;       unsigned int display_width, display_height; &lt;br /&gt;       unsigned int width, height; &lt;br /&gt;       char *display_name = (char*)getenv("DISPLAY");  &lt;br /&gt;       GC gc;   &lt;br /&gt;       XImage* img;&lt;br /&gt;       /* open connection with the X server. */&lt;br /&gt;       display = XOpenDisplay(display_name);&lt;br /&gt;       if (display == NULL) {&lt;br /&gt;               return -1;&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;       screen_num = DefaultScreen(display);&lt;br /&gt;       display_width = DisplayWidth(display, screen_num);&lt;br /&gt;       display_height = DisplayHeight(display, screen_num);&lt;br /&gt;&lt;br /&gt;       width = 720;&lt;br /&gt;       height = 576;&lt;br /&gt;       &lt;br /&gt;       printf("window width - '%d'; height - '%d'\n", width, height);&lt;br /&gt;       &lt;br /&gt;       win = create_simple_window(display, width, height, 0, 0);&lt;br /&gt;       gc = create_gc(display, win, 0);&lt;br /&gt;       XSelectInput(display, win, ExposureMask | KeyPressMask |&lt;br /&gt;                    ButtonPressMask | StructureNotifyMask);&lt;br /&gt;&lt;br /&gt;       img = create_ximage(display, bmpdata, bwidth, bheight, bdepth);&lt;br /&gt;&lt;br /&gt;       XMapWindow(display, win);&lt;br /&gt;       XFlush(display);&lt;br /&gt;       {&lt;br /&gt;               XEvent report;&lt;br /&gt;               while (1)  {&lt;br /&gt;                       XNextEvent(display, &amp;report);&lt;br /&gt;                       switch  (report.type) {&lt;br /&gt;                       case Expose:&lt;br /&gt;&lt;br /&gt;                               if (report.xexpose.count != 0)&lt;br /&gt;                                     break;&lt;br /&gt;&lt;br /&gt;                               place_graphics(display, win, gc, img, width, height);&lt;br /&gt;                               break;&lt;br /&gt;                       case ConfigureNotify:&lt;br /&gt;                               &lt;br /&gt;                               break;&lt;br /&gt;                       case ButtonPress:&lt;br /&gt;&lt;br /&gt;                       case KeyPress:&lt;br /&gt;&lt;br /&gt;                               break;&lt;br /&gt;                               &lt;br /&gt;                       default:&lt;br /&gt;&lt;br /&gt;                               break;&lt;br /&gt;                       } /* End switch */&lt;br /&gt;               } /* End while */&lt;br /&gt;       }&lt;br /&gt;       return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char** argv)&lt;br /&gt;{&lt;br /&gt;       char filename[256];&lt;br /&gt;       unsigned char* data;&lt;br /&gt;       unsigned char* buffer;&lt;br /&gt;       int width, height, depth;&lt;br /&gt;&lt;br /&gt;       strcpy(filename, "/root/a.bmp");&lt;br /&gt;       if(argc == 2) {&lt;br /&gt;               strcpy(filename, argv[1]);&lt;br /&gt;       }&lt;br /&gt;       buffer = (unsigned char*) malloc(2*1024*1024);&lt;br /&gt;       if(buffer == NULL) {&lt;br /&gt;               return -1;&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;       data = NULL;&lt;br /&gt;       read_bmp_file(filename, buffer, &amp;data, &amp;amp;width, &amp;height, &amp;amp;depth);&lt;br /&gt;       if(data == NULL) {&lt;br /&gt;               free(buffer);&lt;br /&gt;               return -1;&lt;br /&gt;       }&lt;br /&gt;       show_bmp_data(data, width, height, depth);&lt;br /&gt;       free(buffer);&lt;br /&gt;       return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//这里面只是支持32位BMP文件 将BMP数据到IMAGE转换中的最后pp++去掉就可以支持24位BMP&lt;br /&gt;//我现在使用XAllocColor的方法实现256色BMP的显示，这个演示的程序不包含。&lt;br /&gt; &lt;/span&gt;   &lt;p class="small"&gt;文章选项： &lt;a target="_blank" href="http://www.linuxforum.net/forum/printthread.php?Cat=&amp;Board=kylix&amp;amp;main=648433&amp;type=post"&gt;&lt;img alt="打印" src="http://www.linuxforum.net/forum/images/print.gif" align="absmiddle" border="0" /&gt;&lt;/a&gt;              &lt;a href="http://www.linuxforum.net/forum/addfav.php?Cat=&amp;Board=kylix&amp;amp;main=648433&amp;type=reminder&amp;amp;Number=648433&amp;page=0&amp;amp;view=collapsed&amp;sb=5&amp;amp;o=31&amp;vc=1&amp;amp;fpart=1&amp;what=showflat"&gt;&lt;img alt="将这篇文章放置于备忘录中，待有空时回覆" src="http://www.linuxforum.net/forum/images/addreminder.gif" align="top" border="0" /&gt;&lt;/a&gt;                 &lt;a href="http://www.linuxforum.net/forum/mailthread.php?Cat=&amp;Board=kylix&amp;amp;Number=648433&amp;page=0&amp;amp;view=collapsed&amp;sb=5&amp;amp;o=31&amp;vc=1&amp;amp;fpart=1&amp;what=showflat"&gt;&lt;img alt="好友分享" src="http://www.linuxforum.net/forum/images/sendbyemail.gif" align="absmiddle" border="0" /&gt;&lt;/a&gt;                    &lt;a href="http://www.linuxforum.net/forum/notifymod.php?Cat=&amp;Board=kylix&amp;amp;Number=648433&amp;page=0&amp;amp;view=collapsed&amp;sb=5&amp;amp;o=31&amp;vc=1&amp;amp;fpart=1&amp;amp;what=showflat"&gt;&lt;img alt="通知版主" src="http://www.linuxforum.net/forum/images/notifymod.gif" align="absmiddle" border="0" /&gt;&lt;/a&gt;              &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-1017853088262451148?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/1017853088262451148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=1017853088262451148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1017853088262451148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1017853088262451148'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/05/xlibbmp.html' title='写个Xlib的BMP文件显示程序'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-1016125783151939484</id><published>2007-05-05T23:06:00.000+08:00</published><updated>2007-05-05T23:19:32.043+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OCR ANN CNN 卷积神经网络'/><title type='text'>字符识别之卷积神经网络</title><content type='html'>卷积神经网络可以共享权,可以提取图像特征,可以通过设计卷积核和采样方法来实现图像的旋转不变.&lt;br /&gt;我使用了一个卷积神经网络的模型,参考了一个LeCun的文献.&lt;br /&gt;首先将字符图象变成28x28 为什么呢,28能被4整除比较合适.因为我真正在神经网络中识别的是29x29,但是为了从车牌中提取图像方便,把所有图像都归一成28 28.&lt;br /&gt;整个网络设计分为5层. 第一层 是输入层,就是原始的29x29的图像.&lt;br /&gt;第二层分成6个Feature Map. 每个Feature Map包含了一个13x13的图像.每个13x13的图像是从第一层与一个5x5的卷积核卷积而来,这个卷积核在第一层输入的图像X方向和Y方向每隔两个像素移动一次,可以动手画一下,看看是不是能把29x29映射成13x13,我画过了,可以.6个Feature Map就是用 6个不同的卷积核.&lt;br /&gt;第三层分成50个Feature Map,每个Feature Map是5x5像素的图像. 和第一层到第二层的映射方法一样,是一个5x5的卷积核,在第二层的某个Feature Map上移动,移动的方法也是X Y 方向每隔两个像素.再次动手画画,看看是不是13x13能够映射成5x5.&lt;br /&gt;第四层和第五层是全连接层. 第四层100个神经元,第五层是输出层.你想输出多少种变化?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-1016125783151939484?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/1016125783151939484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=1016125783151939484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1016125783151939484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/1016125783151939484'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/05/blog-post_05.html' title='字符识别之卷积神经网络'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8472451159088755609</id><published>2007-05-05T22:43:00.000+08:00</published><updated>2007-05-05T23:04:33.769+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='连通区域 深度优先搜索'/><title type='text'>二值图像区域标示算法</title><content type='html'>对二值图像的连通区域搜索标明.在OpenCV中可以使用cvFindContours来实现,然后再用mini area确定一个Box2D的对象,就可以操作连通区域了,我使用了一下,标示的挺准确(我还没有发现错误),并且速度也很快.&lt;br /&gt;但是我不想因为就使用这一个函数来增加一个库引用的负担,或者我想自己发现连通区域怎么办.当然我就是基于这两个原因,试用了很多算法来标示连通区域.&lt;br /&gt;常见的标号法,就是四连通或者八连通搜索,对一个像素的4个邻域(左,上)或者8个邻域搜索(左,上,左上,右上)来标号,建立一个和原图像像素一样多的整数空间,然后在这个整数空间标号(可以解决区域超过255的情况).标号算法的最大问题就是要重新计算统一区域重复标注的问题.这个问题很是不好弄,所以我最后放弃了标号法.&lt;br /&gt;图的深度优先搜索方法,就是遇到一个关注像素(如白色,黑色是背景),就在这个像素的8邻域内查看如果有关注像素,就把这个像素放到一个栈里面,并且把当前的关注像素标号,然后再把栈里面的像素弹出,同样找这个像素的8邻域,如果有关注像素并且未被标号,那么放入栈,然后标号这个像素.如此反复知道栈见底.这是图的深度优先搜索,如果真的是这样搜索区域的话,真的很慢. 加了些处理后,速度基本可以接受了.首先将整个图像的关注像素全部放入一个链表,因为一般讲背景像素是整个图像中的大多数,这样就避开每次对关注像素搜索的时候要不断地碰到背景像素这样的浪费.再有就是将栈变成静态数组,再加一个索引跟着.这样搜索每个区域的第一个关注点的时候都到链表中去寻找,而不是遍历图像.但是8邻域搜索是必须以图像像素索引的,不能到链表中找.注意链表不能存在像素的拷贝而只是引用,不然在标示的时候不能影响到链表的数据,那么也就不能正确的找到下一个区域的起始关注点.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8472451159088755609?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8472451159088755609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8472451159088755609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8472451159088755609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8472451159088755609'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/05/blog-post.html' title='二值图像区域标示算法'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-731009378740130991</id><published>2007-04-16T15:34:00.000+08:00</published><updated>2007-04-16T16:03:06.277+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='memory leak'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenCV'/><title type='text'>OpenCV使用注意之伪内存泄露</title><content type='html'>在测试和验证各种各样的算法的时候,我使用了Intel的OpenCV.这是个开源的项目,很不错.使用这里面的函数在初期帮我节省了很多时间,虽然现在我已经全部用自己实现的替换掉了,自己写的好控制些,并且速度的确快了一些.不过我也积累了一些小的OpenCV的使用经验,这些经验也是用时间换来的,在此记录下,如果可以节省一点资源就是价值.&lt;br /&gt;在使用cvGetSubRect的时候,我的内存是刷刷的漏掉,当然最开始我怎么也不知道是这个函数漏,一万次的试验才发现,是它在泄露. 我想知道是它在泄露,如何避免就是一件简单的事情了. 最简单的办法就是不用了哈哈,我就是自己写了一个类似的函数,把它暂时替换掉了.实际上是我用错了这个函数,我在使用它的时候为Matric申请了内存,实际上是不需要申请它会把源数据中的内存值直接付给这个Matric的数据指针,这样的结果就是把我实际申请的数据空间指针给覆盖了,我的程序就丢失了这个已经申请的内存区域的地址,我如果去释放这个Matric,那么实际上是释放的Matric的Header和源数据的相应空间,把源给干了,不仅仅是泄露,而且还干了很龌龊的事情.这是后来我查看cvGetSubRect的code时候发现的(cxarray.c 1496).&lt;br /&gt;知道了这些,就知道怎么正确使用这个函数了. cvGetSubRect(). 如果使用它那么请记住我说的.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-731009378740130991?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/731009378740130991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=731009378740130991' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/731009378740130991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/731009378740130991'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/opencv.html' title='OpenCV使用注意之伪内存泄露'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5588872363029893200</id><published>2007-04-16T10:57:00.000+08:00</published><updated>2007-04-16T12:18:59.782+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='image processing'/><category scheme='http://www.blogger.com/atom/ns#' term='Convolution'/><title type='text'>图像处理之卷积概念</title><content type='html'>如果你刚刚接触图像处理,或者离开大学很长时间,一看到卷积这个东西,肯定和我一样感到晕菜.那么就复习一下,并且实际的写个程序验证一下,我保证你这辈子不会再忘记卷积的概念了.我们来看一下一维卷积的概念.&lt;br /&gt;连续空间的卷积定义是 f(x)与g(x)的卷积是 f(t-x)g(x) 在t从负无穷到正无穷的积分值.t-x要在f(x)定义域内,所以看上去很大的积分实际上还是在一定范围的.&lt;br /&gt;实际的过程就是f(x) 先做一个Y轴的反转,然后再沿X轴平移t就是f(t-x),然后再把g(x)拿来,两者乘积的值再积分.想象一下如果g(x)或者f(x)是个单位的阶越函数. 那么就是f(t-x)与g(x)相交部分的面积.这就是卷积了.&lt;br /&gt;把积分符号换成求和就是离散空间的卷积定义了.那么在图像中卷积卷积地是什么意思呢,就是图像就是图像f(x),模板是g(x),然后将模版g(x)在模版中移动,每到一个位置,就把f(x)与g(x)的定义域相交的元素进行乘积并且求和,得出新的图像一点,就是被卷积后的图像. 模版又称为卷积核.卷积核做一个矩阵的形状.&lt;br /&gt;卷积定义上是线性系统分析经常用到的.线性系统就是一个系统的输入和输出的关系是线性关系.就是说整个系统可以分解成N多的无关独立变化,整个系统就是这些变化的累加.&lt;br /&gt;如 x1-&gt;y1, x2-&gt;y2; 那么A*x1 + B*x2 -&gt; A*y1 + B*y2 这就是线性系统. 表示一个线性系统可以用积分的形式 如 Y = Sf(t,x)g(x)dt S表示积分符号,就是f(t,x)表示的是A B之类的线性系数.&lt;br /&gt;看上去很像卷积呀,,对如果f(t,x) = F(t-x) 不就是了吗.从f(t,x)变成F(t-x)实际上是说明f(t,x)是个线性移不变,就是说 变量的差不变化的时候,那么函数的值不变化. 实际上说明一个事情就是说线性移不变系统的输出可以通过输入和表示系统线性特征的函数卷积得到.&lt;br /&gt;&lt;br /&gt;哈哈,我也有点晕了.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5588872363029893200?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5588872363029893200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5588872363029893200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5588872363029893200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5588872363029893200'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post_1486.html' title='图像处理之卷积概念'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-2512289296505884299</id><published>2007-04-16T10:52:00.000+08:00</published><updated>2007-04-16T10:55:24.580+08:00</updated><title type='text'>车牌识别-水平微分之递增算法</title><content type='html'>将原始彩色图像转换成灰度图象之后,对灰度图象进行水平微分&lt;div style="direction: ltr;"&gt;&lt;wbr&gt;,微分的方法是先做水平均值然后再微分,具体方法参考了一个文献&lt;wbr&gt;的描述:使用一个水平模板算子，即[1,1,1…，1，1，1&lt;wbr&gt;，1]。该算子与图像进行卷积然后再与原图像作差分运算&lt;wbr&gt;，当差分值大于某一门限值就认为它是边缘目标，否则是背景。&lt;br /&gt;&lt;br /&gt;水平模板即[1,1,1…，1，1，1，1]，它与图像进行卷积&lt;wbr&gt;相当于图像水平方向进行低通滤波，再与原图像差分&lt;wbr&gt;，其目的是突出图像的垂直方向的高频信息（相当于对图像进行高通&lt;wbr&gt;滤波）。由于该算子可以做增量运算，也就是在计算局部平均值时&lt;wbr&gt;，先计算水平方向窗口内各点之和，将前次运算的结果减去窗口最左&lt;wbr&gt;边点的值再加上右边新一点的值。这样可以减少求和运算次数.&lt;br /&gt;&lt;br /&gt;算子的长度多少的选择要看一个车牌字符的宽度大致应该是多少&lt;wbr&gt;,比如9,说明比较适合9个像素宽度的字符.&lt;br /&gt;&lt;br /&gt;下面是我的实现:&lt;br /&gt;里面有最大值统计,可以根据最大值来动态调节二值化的域值&lt;wbr&gt;,也可以是固定的比如10,影响不是很大.&lt;br /&gt;&lt;br /&gt;typedef struct {&lt;br /&gt; int width;&lt;br /&gt; int height;&lt;br /&gt; int width_step;&lt;br /&gt; int channel;&lt;br /&gt; unsigned char* image_data;&lt;br /&gt;} t_image;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int pre_delta(t_image* src, t_image* dst)&lt;br /&gt;{&lt;br /&gt; int height=src-&gt;height;&lt;br /&gt; int width=src-&gt;width;&lt;br /&gt; int x, y;&lt;br /&gt;&lt;br /&gt; unsigned int v;&lt;br /&gt; unsigned char *p, *q;&lt;br /&gt; int i, u;&lt;br /&gt;&lt;br /&gt; int max_u = 0;&lt;br /&gt;&lt;br /&gt; for(y=0; y&lt;height; y++) {&lt;br /&gt;         p = src-&gt;image_data + src-&gt;width_step*y;&lt;br /&gt;         q = dst-&gt;image_data + dst-&gt;width_step*y;&lt;br /&gt;         v = 0;&lt;br /&gt;   for(i = 0; i &lt; 9; i++) {&lt;br /&gt;                 v += *(p++);&lt;br /&gt;         }&lt;br /&gt;   for(x=5; x&lt;width-4; x++) {&lt;br /&gt;                 v -= *(p - 9);&lt;br /&gt;                 v += *(p++);&lt;br /&gt;                 u = (v/9 - *(p-5));&lt;br /&gt;                 if(u &gt; 0) {&lt;br /&gt;                   if(u &gt; max_u)&lt;br /&gt;                     max_u = u;&lt;br /&gt;                   *(q+x) = (unsigned char)u;&lt;br /&gt;                 }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;参考文献:&lt;br /&gt;一种边缘检测与扫描线相结合的车牌定位算法&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-2512289296505884299?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/2512289296505884299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=2512289296505884299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2512289296505884299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/2512289296505884299'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post_16.html' title='车牌识别-水平微分之递增算法'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5080960197550387524</id><published>2007-04-15T22:46:00.000+08:00</published><updated>2007-04-15T22:56:19.805+08:00</updated><title type='text'>车牌识别实现--字符识别</title><content type='html'>别看车牌只是几个字符,但是识别出来还是有点难度的,因为字符提取出来的效果差距很大.提取的字符可能模糊可能倾斜,可能粗可能细,也可能断裂,我四处寻找可以参考的细化的算法,很遗憾没有好的,细化出来的效果很差,不是算法太差,就是原始图像太差,怎么办呢. 终于我找到了解决之道,就是不细化直接识别.这需要卷积神经网络,这个东西太爽了,在教科书上提及很少的共享权重的神经网络,有人在98年就用它来设计识别手写英文字符,这个文献我仔细研读了,并且作者实现的识别率惊人得高,99%多,给我很大信心,我设计了一个卷积神经网络,初步训练和测试效果很好,训练收敛很好,识别也很准确.我没有时间制作大量样本,如果有大量样本数据训练,这个网络表现会更好.&lt;br /&gt;今天写道这里,基本的原理我都写了.真正有价值的就这些了.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5080960197550387524?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5080960197550387524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5080960197550387524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5080960197550387524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5080960197550387524'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post_2726.html' title='车牌识别实现--字符识别'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5691800308945559525</id><published>2007-04-15T22:26:00.000+08:00</published><updated>2007-04-15T22:46:05.412+08:00</updated><title type='text'>车牌识别实现--字符分割</title><content type='html'>以前我想定位了,分割很容易了, 垂直做个投影不就OK了.事实上远远不是这样,因为定位的结果可能错的也可能是好的,也可能含有严重干扰.简单处理是不行的. 首先拿到定位出来的车牌,要分析出来这个车牌的字符和背景的颜色,哪个更黑或者更白,如果这个没有其他都是费.&lt;br /&gt;分析颜色对比,我没有找到合适的文献说明,我自己设计了一个,也许有人已经用过这样的方法,我又在发明相同的轮子了,呵呵不管了,有轮子也好哇. 还是将灰度车牌图像做微分,不过是全微分,这样出来的车牌图像是个灰度微分图,在灰度微分图的最中间的1/4区域内做垂直投影,找到一系列的大的求和点和一系列小值和点,这样基本可以想象这些大值点应该是字符边缘,而小值点是背景,也可能是字符内部.在原有车牌灰度上找这些大值点的像素值, 再找到这些小值点的像素值,小值点像素值要做处理,如果变化很大,说明真的有字符里面的像素也有背景像素,要参考一下刚才发现的字符平均像素,把这些像素去掉.这样就清静了,肯定都是背景了.再比较背景和字符像素的灰度值发现字符黑还是背景黑.&lt;br /&gt;&lt;br /&gt;然后将图像二值化,二值化的方法很多,都不是很有效果,原因是定位的结果可能很不同,我用了一个文献的算法将车牌字符占用比例考虑进去再这个小的邻域内进行最大类间方差和最小类内方差判别,来得到二值化车牌.&lt;br /&gt;&lt;br /&gt;提取字符过程又要区域分割,这里面涉及很多奇妙的东西,参考很多文献,先找到几个相似的区域,如果没有相似区域说明这个车牌图像质量太差,从相似区域里面找最大区域,以这个区域作为样板. 分割之,经常有断裂和连接的情况,通过样板的方法很容易搞定.也许你没有看到倾斜矫正这个过程,因为字符是通过区域提取得到的,所以车牌的倾斜是不需要矫正的,(倒是字符识别的时候会遇到倾斜的字符).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5691800308945559525?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5691800308945559525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5691800308945559525' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5691800308945559525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5691800308945559525'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post_8131.html' title='车牌识别实现--字符分割'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-340261018389521396</id><published>2007-04-15T21:58:00.000+08:00</published><updated>2007-04-15T22:25:57.284+08:00</updated><title type='text'>车牌识别实现--粗定位算法</title><content type='html'>首先,我想说明的是很多的想法不是我原创的,但是程序都是我写的.我在这里把我几个月来对车牌定位和识别的设计实现以及试验的过程记录下来,为了自己不断忘却的记忆,也许能帮上你的忙,那我就会感谢没有浪费你的时间.我为我没有做到不利于别人的事情而感到安慰,呵呵.&lt;br /&gt;   我选择的定位方式是基于纹理的分析,通过微分图像,将车牌的字符变化突出出来,然后选择一个值进行微分图像二值化,这个值的选择看上去很重要,其实不是很重要,我试验了固定的数10,或者微分图像的最大值推算一个接近10的数,得到的图像虽然不同,但是字符的水平纹理基本不受太大影响.然后要对二值化微分图像进行处理,在很多文献上提到颗粒滤波和长程曲线滤波,我借鉴了颗粒滤波和长程曲线滤波的想法,但是重新简化了算法,颗粒滤波不是针对颗粒的周围只是针对其上下边界进行计算,因为我要寻找纹理的水平方向上的变化,颗粒滤波的效果很好,并且能够实现快速匹配运算,提高效率,长程滤波困扰了我很长时间,最后还是用了一个笨方法但是实际速度还是可以接受,我专门写了一个帖子以示纪念.&lt;br /&gt; 核心的过程实际上是对二值图像的水平纹理变化扫描统计,扫描到车牌特征区域,并且把这个区域记下.车牌特征区域实际上不是一下能够定位出来的,扫描只是一个准备过程,就是相当于把这个问题分解,那么扫描的过程也就不会非常难实现.扫描到在X方向上一段距离内像素值变化在9-50范围就可能是车牌,把这个扫描线放到一个新的图像中,这是很关关键,这样在一个临时存储的图像中就会用很多很多扫描线,这些线是通过对二值图像的变化扫描出来的,需要使用简单的状态机,不然程序就太乱了.临时图像的有很多扫描线,这些扫描线都像发现了车牌一样. 这时候我把精力转移到处理这个有扫描线的临时图像上,其中我自己设计了腐蚀和膨胀算法,因为传统腐蚀与膨胀算法是针对所有目标区域的,但是我不想这样,因为我在腐蚀的时候,我只希望专门沿着X方向或者专门沿着Y方向把不合适大小的连续扫描线去掉,而不对那些看上去真的很合适的扫描线进行形态操作,不影响它,根本就不动它. 通过这样的处理后再将区域进行标识,区域标识我用的两条直线同在一个区域的判别方法,这个方法很快,但是会有很明显的共区域现象.需要重新处理,好在在这个时候区域已经很少,选择什么算法,对速度影响不大.&lt;br /&gt; 到这里定位基本结束,90%以上的车牌就是最底下的候选区域.清晰的车牌很容易定位,不清晰的车牌即使勉强定位成功,识别也是很难.因为下面的字符分割也是个麻烦.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-340261018389521396?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/340261018389521396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=340261018389521396' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/340261018389521396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/340261018389521396'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post_15.html' title='车牌识别实现--粗定位算法'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7778588060915355300</id><published>2007-04-15T20:29:00.000+08:00</published><updated>2007-04-15T20:51:23.515+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LPR'/><category scheme='http://www.blogger.com/atom/ns#' term='image processing'/><title type='text'>一种长程曲线的滤波方法</title><content type='html'>一种长程曲线的滤波方法&lt;br /&gt;很久没有来这里了,最近一直在忙于实现一个自动车牌定位和识别的算法,感谢互联网为我提供了很多素材,最终我采用了基于纹理分析的方法.但是在微分图像中有很长的边缘干扰,类似汽车的边界,这些长程曲线干扰如何去掉,困扰了我很久,有文献上略略提到,但是没有明确和实现的方法.我设计了一个方法,也许不是最好的,但是还比较好用.&lt;br /&gt;具体的算法是,在微分图像中进行8连通的区域搜索,用标记法搜索,不用二次修正,因为是竖长曲线搜索,如果是标记错误,那么影响很小.对于搜索出来的区域寻找Y轴的最大小值,如果最大值和最小值之间距大于你的想象了(一般是整幅图像的1/10)那么这是一个干扰长线区域,应该去掉.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7778588060915355300?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7778588060915355300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7778588060915355300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7778588060915355300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7778588060915355300'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/04/blog-post.html' title='一种长程曲线的滤波方法'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-604224751415531470</id><published>2007-01-21T14:21:00.000+08:00</published><updated>2007-01-21T15:07:54.867+08:00</updated><title type='text'>Using doxygen with CJK-latex</title><content type='html'>Make sure you have installed the latast doxygen CJK-latex and related fonts. Create doxygen config file support Chinese language and make sure output format including latex.&lt;br /&gt;&lt;br /&gt;After generate document you will get the latex directory. Change directory to latex and edit the main tex file maybe "refmain.tex". Add the line "\usepackage{CJK}" after "\usepackage{doxygen}".&lt;br /&gt;Add the line "\begin{CJK*}{GB}{song}" after "\begin{document}"&lt;br /&gt;Add the line "\end{CJK*} before \end{document}&lt;br /&gt;&lt;br /&gt;and run latex refman.tex you will the refman.dvi that supports chinese.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-604224751415531470?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/604224751415531470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=604224751415531470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/604224751415531470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/604224751415531470'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/using-doxygen-with-cjk-latex.html' title='Using doxygen with CJK-latex'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7760202915853919228</id><published>2007-01-19T17:34:00.000+08:00</published><updated>2007-01-19T17:44:02.401+08:00</updated><title type='text'>Using Apache2 SSL in Debian</title><content type='html'>If you have virtualhost define.&lt;br /&gt;first add  a listen port to  port.conf&lt;br /&gt;    Listen 80&lt;br /&gt;    Listen 443   --- new line&lt;br /&gt;second add a virtualhost name in apache2.conf&lt;br /&gt;    VirtualHost *:80&lt;br /&gt;    VirtualHost *:433 --- new line&lt;br /&gt;third add a virtual host to your virtual host define for example a tootoosoft_com file in sites-available directory.&lt;br /&gt;copy original virtualhost definition and modify the name from *:80 to *:443&lt;br /&gt;add&lt;br /&gt;    SSLEngine on&lt;br /&gt;    SSLCertificateFile /etc/apache2/ssl/apache.pem&lt;br /&gt;&lt;br /&gt;restart apache. test any page just replace url http to https&lt;br /&gt;&lt;br /&gt;this link has some detail info.&lt;br /&gt;&lt;a href="http://www.debian-administration.org/articles/349"&gt;http://www.debian-administration.org/articles/349&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7760202915853919228?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7760202915853919228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7760202915853919228' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7760202915853919228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7760202915853919228'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/using-apache2-ssl-in-debian.html' title='Using Apache2 SSL in Debian'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-579467389330651546</id><published>2007-01-17T14:50:00.000+08:00</published><updated>2007-01-17T16:06:28.391+08:00</updated><title type='text'>Install Apache2 with mod_ssl</title><content type='html'>在apache2中SSL的支持已经内置，不需要再单独现在MOD SSL这个软件了。那么只需要编译这个DSO就可以了，apache中支持DSO的方法就是调用动态库没有什么 奇招。那么编译的时候 --enable-so --enable-ssl=static 用static可以将openssl的函数编译到mod_ssl中这样一旦openssl的动态库不在也可以使用。并且openssl有的安装默认是不编译动态库的，比较谨慎。&lt;br /&gt;当然还需要创建服务器端的SSL证书和私钥。可以通过一个工具在http://www.openssl.org/contrib/ssl.ca-0.1.tar.gz&lt;br /&gt;解压缩然后首先生成 ROOT CA的自签发证书和ROOT CA的私钥，然后再生成服务器证书请求和服务器私钥，通过ROOT CA进行服务器证书的签发。然后将服务器证书和私钥复制到合适路径这些文件的路径要在http.conf中明确表示。&lt;br /&gt;http conf一般通过打开 http-ssl conf注释来引用ssl的配置信息。那么检查该配置文件，确认你的证书都能被他找到。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-579467389330651546?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/579467389330651546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=579467389330651546' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/579467389330651546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/579467389330651546'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/intall-apache2-with-modssl.html' title='Install Apache2 with mod_ssl'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6148765616264028432</id><published>2007-01-17T14:42:00.000+08:00</published><updated>2007-01-17T14:48:52.360+08:00</updated><title type='text'>Reinstall Apache2</title><content type='html'>当你已经安装一个apache2 ，比如目录/usr/local/apache2.你是不能够再从源码编译Apache2的.为什么呢，因为Apache2的configure中做了判断,它会search $lookdir 其中就包含了 /usr/local/apache2 你只需要把它放到一个不是$lookdir覆盖的目录就可以了.lookdir是configure里面指定的一组目录.现在包含 /usr /usr/local /usr/local/apr /opt/apr /usr/local/apache2&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6148765616264028432?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6148765616264028432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6148765616264028432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6148765616264028432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6148765616264028432'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/reinstall-apache2.html' title='Reinstall Apache2'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8596546327811259868</id><published>2007-01-17T10:51:00.000+08:00</published><updated>2007-01-17T10:55:08.764+08:00</updated><title type='text'>Install Apache2 Mysql PHP XOOPS from scrible</title><content type='html'>1) install mysql&lt;br /&gt;configure --prefix=/usr/lcoal/mysql/&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;mysql_install_db&lt;br /&gt;&lt;br /&gt;mysqld_safe&lt;br /&gt;(check the mysql user add, adduser mysql)&lt;br /&gt;&lt;br /&gt;change root password for mysql, default root password is nothing&lt;br /&gt;mysqladmin -u root password "newpassword"&lt;br /&gt;&lt;br /&gt;login test&lt;br /&gt;mysqladming -uroot -pxxx mysql&lt;br /&gt;&lt;br /&gt;2) install apache2&lt;br /&gt;configure --prefix=/usr/local/apache2/ --enable-so --enable-mods-shared=most&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;&lt;br /&gt;3) install php&lt;br /&gt;configure --prefix=/usr/local/php/ --with-mysql=/usr/local/mysql --with-apxs2=/usr/local/apache2/bin/apxs  --with-gd --enable-gd-native-ttf --with-ttf --with-gettext --with-iconv --with-png --with-zlib --with-xml --enable-calendar&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;it will modify the httpd.conf ucomment line&lt;br /&gt;&lt;br /&gt;LoadModule php4_module        modules/libphp4.so&lt;br /&gt;&lt;br /&gt;4) apache2 config&lt;br /&gt;edit http.conf add the following two lines in the section mime_module&lt;br /&gt;&lt;br /&gt;&lt;ifmodule&gt;&lt;br /&gt;...&lt;br /&gt;  AddType application/x-httpd-php .php&lt;br /&gt;  AddType application/x-httpd-php-source .phps&lt;br /&gt;...&lt;br /&gt;&lt;ifmodule&gt;&lt;br /&gt;&lt;br /&gt;5) XOOPS&lt;br /&gt;copy xoops/html/* to htdocs (apache DocumentRoot)&lt;br /&gt;chmod 777 cache&lt;br /&gt;chmod 777 template_c&lt;br /&gt;chmod 777 mainfile.php&lt;br /&gt;chmod 777 uploads&lt;br /&gt;create database xoops in mysql&lt;br /&gt;firefox browse the root http://localhost/&lt;br /&gt;than in the wizard you will get next-&gt;next-&gt;next ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8596546327811259868?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8596546327811259868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8596546327811259868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8596546327811259868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8596546327811259868'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/install-apache2-mysql-php-xoops-from.html' title='Install Apache2 Mysql PHP XOOPS from scrible'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-322072426727386538</id><published>2007-01-14T10:18:00.000+08:00</published><updated>2007-01-14T10:21:04.133+08:00</updated><title type='text'>Remove "wintems.exe" trojan manually - 2</title><content type='html'>删除了wintems之后，但是还是不行，经常能看到iexplore经常 自己启动，我正在操作得软件也经常失去焦点。这是怎么回事肯定是什么软件，启动iexplorer。待我慢慢寻之。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-322072426727386538?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/322072426727386538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=322072426727386538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/322072426727386538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/322072426727386538'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/remove-wintemsexe-trojan-manually-2.html' title='Remove &quot;wintems.exe&quot; trojan manually - 2'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5537381047678291509</id><published>2007-01-14T08:13:00.000+08:00</published><updated>2007-01-14T08:31:39.283+08:00</updated><title type='text'>Remove "wintems.exe" trojan manually</title><content type='html'>很久以来 ，我都没有使用杀毒软件，一旦发现系统变慢，我就观察是否有中毒。这几天在写一些VC的程序的时候，经常失去自己键盘的焦点， 很是恼火，原来是系统中了一个 wintems.exe 的Trojan。这个东西会导致iexplore干一些事情，我在系统刚刚启动的时候执行了 ethereal抓到了无数的自动访问 xxxx N多的网站。简直是疯狂。 决定手动干掉它，因为各种杀毒软件实在是太笨，并且特别耗资源，我这个机器只有300多M的内存， PIII的CPU，我一直让他保持20个以内的进程运行，所以一旦有什么异样，我能立刻发现，并且干掉它。&lt;br /&gt;&lt;br /&gt;检查你的进程列表 如果有 wintem.exe 那么很荣幸，你中着了。然后再检查注册表 regedit.exe，看HKCU\SOFTWARE\DateTimeN，N可能是1，2，3，4之类的数字，那么说明你正在中招。干掉它。每个机器的感染现象不一样，所以杀毒软件是不一定能解决问题的，得通过你的观察。&lt;br /&gt;&lt;br /&gt;我得iexplore一定是被注入东西了，经常无缘无故得自己运行，所以需要换一个干净得。然后wintems这个进程一定要停止调。&lt;br /&gt;&lt;br /&gt;下次再写详细得手动 杀毒步骤，但是这未必适合你，因为我们中得毒和系统得环境都不同，处于病毒得变化状态也不相同，所以不变得使用我得方法未必有效，但是这个杀毒得方法还是可以得，需要点时间，但是我觉得 比杀毒软件在自己得机器上漫无目的瞎搞要好得多。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5537381047678291509?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5537381047678291509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5537381047678291509' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5537381047678291509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5537381047678291509'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/remove-wintemsexe-trojan-manually.html' title='Remove &quot;wintems.exe&quot; trojan manually'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5175947085580932472</id><published>2007-01-11T10:17:00.000+08:00</published><updated>2007-01-11T10:30:51.179+08:00</updated><title type='text'>Using apache2 VirtualHost in Debian</title><content type='html'>In Debian apache2's config file is /etc/apache/apache2.conf&lt;br /&gt;&lt;br /&gt;The botom line in the config file "Include /etc/apache2/sites-enabled/". That means apache2 will use the file in the directory as virtualhost.&lt;br /&gt;Goto the directory you will find nothing or a symbolic file "000-default". It is OK. Actually the virtualhost config in the directory "/etc/apache2/sites-available".&lt;br /&gt;&lt;br /&gt;For example you want add a virtual host named tootoosoft.com to the existing apache. Now create a file in the /etc/apache2/sites-available/  named tootoosoft_com (anything is ok). edit it just like following:&lt;br /&gt;&lt;br /&gt;NameVirtualHost *&lt;br /&gt;&lt;virtualhost&gt;&lt;br /&gt;        ServerName www.tootoosoft.com&lt;br /&gt;&lt;br /&gt;        DocumentRoot /var/www/tootoosoft_com&lt;br /&gt;        &lt;directory&gt;&lt;br /&gt;                Options FollowSymLinks&lt;br /&gt;                AllowOverride None&lt;br /&gt;        &lt;/directory&gt;&lt;br /&gt;        &lt;directory&gt;&lt;br /&gt;                Options Indexes FollowSymLinks MultiViews&lt;br /&gt;                AllowOverride None&lt;br /&gt;                Order allow,deny&lt;br /&gt;                allow from all&lt;br /&gt;        &lt;/directory&gt;&lt;br /&gt;&lt;br /&gt;        LogLevel warn&lt;br /&gt;&lt;br /&gt;        CustomLog /var/log/apache2/access.log combined&lt;br /&gt;        ServerSignature On&lt;br /&gt;&lt;br /&gt;&lt;/virtualhost&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NameHost *, the * means any IP interface in the host.&lt;br /&gt;then create a symbolic "/etc/apache2/sites-enabled"&lt;br /&gt;# ln -sf /etc/apache2/sites-available/tootoosoft_com /etc/apache2/sites-enabled/tootoosoft_com&lt;br /&gt;&lt;br /&gt;Restart apache2&lt;br /&gt;#/etc/init.d/apache restart&lt;br /&gt;&lt;br /&gt;If you want add more just create file in sites-available and create symbolic file in sites-enabled and restart apache you will get it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5175947085580932472?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5175947085580932472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5175947085580932472' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5175947085580932472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5175947085580932472'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/using-apache2-virtualhost-in-debian.html' title='Using apache2 VirtualHost in Debian'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-5721706717773025546</id><published>2007-01-06T23:27:00.000+08:00</published><updated>2007-01-06T23:34:11.333+08:00</updated><title type='text'>Using Libjingle</title><content type='html'>Libjingle give us a selection to develop a p2p voice tools. You certainly can select a commercial Voice Engine (GIPS) but the ICE and the framework is still very important. It token me three days to develop a Linux p2p ip phone based libjingle and GTK2. It is very interesting but if you want to build a solution. Libjingle is not enough. More is your business.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-5721706717773025546?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/5721706717773025546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=5721706717773025546' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5721706717773025546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/5721706717773025546'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/using-libjingle.html' title='Using Libjingle'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-3012601889329129945</id><published>2007-01-06T23:19:00.000+08:00</published><updated>2007-01-06T23:26:54.297+08:00</updated><title type='text'>Asterisk release 1.4.0</title><content type='html'>Asterisk the open source PBX but hardware not :). It is really a good idea to sale the compatible interface card. But the LIBPRI, chan-ss7 and some related open source project is very interesting .&lt;br /&gt;&lt;br /&gt;http://www.asterisk.org&lt;br /&gt;&lt;br /&gt;If you want to get a open source ss7 implementation the chan-ss7 is a good begining better than openss7 (it is not really open because I can not see it is valid code).&lt;br /&gt;&lt;br /&gt;http://www.sifira.dk/chan-ss7/&lt;br /&gt;&lt;br /&gt;the latest version 0.8.4.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-3012601889329129945?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/3012601889329129945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=3012601889329129945' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3012601889329129945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/3012601889329129945'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/asterisk-release-140.html' title='Asterisk release 1.4.0'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6392278017777962252</id><published>2007-01-06T23:12:00.000+08:00</published><updated>2007-01-06T23:16:39.547+08:00</updated><title type='text'>OpenH323 status</title><content type='html'>&lt;span style="font-family: arial;"&gt;It is long time I had not take time on researching the project. It's major site has&lt;/span&gt; not updated since 2004. SF has the latest.&lt;br /&gt;&lt;br /&gt;http://sourceforge.net/projects/openh323&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6392278017777962252?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6392278017777962252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6392278017777962252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6392278017777962252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6392278017777962252'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/openh323-status.html' title='OpenH323 status'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6361399847805011734</id><published>2007-01-06T20:15:00.000+08:00</published><updated>2007-01-06T20:16:29.911+08:00</updated><title type='text'>My DOT EMACS .emacs support chinese fontset emacs23</title><content type='html'>(set-language-environment 'Chinese-GB)&lt;br /&gt;(set-keyboard-coding-system 'euc-cn)&lt;br /&gt;(set-clipboard-coding-system 'euc-cn)&lt;br /&gt;(set-terminal-coding-system 'euc-cn)&lt;br /&gt;(set-buffer-file-coding-system 'euc-cn)&lt;br /&gt;(set-selection-coding-system 'euc-cn)&lt;br /&gt;(modify-coding-system-alist 'process "*" 'euc-cn)&lt;br /&gt;(setq default-process-coding-system&lt;br /&gt;      '(euc-cn . euc-cn))&lt;br /&gt;(setq-default pathname-coding-system 'euc-cn)&lt;br /&gt;(tool-bar-mode nil)&lt;br /&gt;(menu-bar-mode nil)&lt;br /&gt;(scroll-bar-mode nil)&lt;br /&gt;(global-font-lock-mode t)&lt;br /&gt;(transient-mark-mode t)&lt;br /&gt;(display-time)&lt;br /&gt;(column-number-mode t)&lt;br /&gt;(show-paren-mode t)&lt;br /&gt;(fset 'yes-or-no-p 'y-or-n-p)&lt;br /&gt;(setq visible-bell t)&lt;br /&gt;;(setq lazy-lock-defer-on-scrolling t)&lt;br /&gt;;(setq font-lock-support-mode 'lazy-lock-mode)&lt;br /&gt;;(setq font-lock-maximum-decoration t)&lt;br /&gt;(setq-default indent-tabs-mode nil)&lt;br /&gt;;(highlight-current-line-on t)&lt;br /&gt;;(highlight-current-line-set-bg-color "sea green")&lt;br /&gt;;(highlight-current-line-set-bg-color "light green")&lt;br /&gt;&lt;br /&gt;(add-hook 'c-mode-hook 'linux-c-mode)&lt;br /&gt;(add-hook 'c++-mode-hook 'linux-cpp-mode)&lt;br /&gt;;; imenu&lt;br /&gt;(setq imenu-sort-function 'imenu--sort-by-name)&lt;br /&gt;(defun linux-c-mode()&lt;br /&gt;  (define-key c-mode-map [return] 'newline-and-indent)&lt;br /&gt;  (interactive)&lt;br /&gt;  (c-set-style "K&amp;R")&lt;br /&gt;  (c-toggle-auto-state)&lt;br /&gt;  (c-toggle-hungry-state)&lt;br /&gt;  (setq c-basic-offset 8)&lt;br /&gt;  (imenu-add-menubar-index)&lt;br /&gt;  (which-function-mode)&lt;br /&gt;  )&lt;br /&gt;(defun linux-cpp-mode()&lt;br /&gt;  (define-key c++-mode-map [return] 'newline-and-indent)&lt;br /&gt;  (define-key c++-mode-map [(control c) (c)] 'compile)&lt;br /&gt;  (interactive)&lt;br /&gt;  (c-set-style "K&amp;R")&lt;br /&gt;  (c-toggle-auto-state)&lt;br /&gt;  (c-toggle-hungry-state)&lt;br /&gt;  (setq c-basic-offset 8)&lt;br /&gt;  (imenu-add-menubar-index)&lt;br /&gt;  (which-function-mode)&lt;br /&gt;  )&lt;br /&gt;&lt;br /&gt;(setq inhibit-startup-message t)&lt;br /&gt;&lt;br /&gt;(setq font-encoding-alist&lt;br /&gt;      (cons '("gb2312.1980" . chinese-gbk) font-encoding-alist))&lt;br /&gt;&lt;br /&gt;(create-fontset-from-fontset-spec&lt;br /&gt; "-*-fixed-medium-r-*-*-20-*-*-*-*-*-fontset-chinese,&lt;br /&gt;    chinese-gb2312:-default-song-medium-r-*--*-*-*-*-*-*-gb2312.1980-0" t)&lt;br /&gt;&lt;br /&gt;(setq default-frame-alist&lt;br /&gt;      (append&lt;br /&gt;       '((font . "fontset-chinese"))&lt;br /&gt;       default-frame-alist))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6361399847805011734?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6361399847805011734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6361399847805011734' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6361399847805011734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6361399847805011734'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/my-dot-emacs-emacs-support-chinese.html' title='My DOT EMACS .emacs support chinese fontset emacs23'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7390687180910098036</id><published>2007-01-06T17:58:00.000+08:00</published><updated>2007-01-06T18:52:08.615+08:00</updated><title type='text'>Install Emacs23 with antialias</title><content type='html'>Check out the latest EMACS23&lt;br /&gt;&lt;br /&gt;#cvs -d   :pserver:anonymous@cvs.savannah.gnu.org:/sources/emacs co emacs&lt;br /&gt;#cd emacs&lt;br /&gt;#./configure --with-xft=yes --with-x-toolkit=gtk --with-gtk=yes&lt;br /&gt;#make bootstrap&lt;br /&gt;In the step you will get many errors. just edit your emacs/src/Makefile add the cairo and glib include directory. Using pkg-config to find. Run pkg-config --cflags gtk+-2.0 you will find "-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr//include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include". Check the line in Makefile add the miss cairo and glib include directory. save the file(if using vi you will get the read only file just type :x!).&lt;br /&gt;&lt;br /&gt;#make; make install&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7390687180910098036?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7390687180910098036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7390687180910098036' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7390687180910098036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7390687180910098036'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/install-emacs23-with-antialias.html' title='Install Emacs23 with antialias'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-570772092232252297</id><published>2007-01-06T17:45:00.000+08:00</published><updated>2007-01-06T17:57:48.607+08:00</updated><title type='text'>Compile GTK+ with Cairo</title><content type='html'>Get latest cairo distribution from http://cairographics.org/. Get latest gtk lib from http://www.gtk.org including glib pango and gtk. You also need the latest libpng atk and latest pkg-config.&lt;br /&gt;&lt;br /&gt;First compile pkg-config and install it. you can set pkg-config search path using PKG_CONFIG_PATH. pkg-config use this enviroment variable to search the directory find the installed package. Every pacage want to be managed by pkg-config has a .pc file that indicate what details information related the package.&lt;br /&gt;&lt;br /&gt;Then compile libpng and install it.&lt;br /&gt;&lt;br /&gt;Then compile glib and isntall it.&lt;br /&gt;&lt;br /&gt;Then compile cario and install it.&lt;br /&gt;&lt;br /&gt;Then pango make sure pango prompt you it using XFT and Cairo to render.&lt;br /&gt;&lt;br /&gt;Then gtk+. If you have any trouble, please let me known I will try it and modify this notes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-570772092232252297?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/570772092232252297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=570772092232252297' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/570772092232252297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/570772092232252297'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/compile-gtk-with-cairo.html' title='Compile GTK+ with Cairo'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-7998111696474076464</id><published>2007-01-03T17:43:00.000+08:00</published><updated>2007-01-03T22:05:38.042+08:00</updated><title type='text'>使用graphviz</title><content type='html'>一直有个任务，没有去完成，每次惭愧的时候都挤出一点时间来考虑一下，但是东东西西的零散开去，没有积累。看到这个东西，或者可以用用。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;http://www.graphviz.org/&lt;br /&gt;http://www-128.ibm.com/developerworks/cn/linux/l-graphvis/?ca=dwcn-newsletter-linux&lt;br /&gt;http://www-128.ibm.com/developerworks/linux/library/l-graphvis/&lt;br /&gt;http://www.blogjava.net/cap/archive/2005/07/17/7895.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-7998111696474076464?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.graphviz.org/' title='使用graphviz'/><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/7998111696474076464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=7998111696474076464' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7998111696474076464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/7998111696474076464'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/graphviz.html' title='使用graphviz'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-6170371626131600219</id><published>2007-01-03T16:35:00.001+08:00</published><updated>2007-01-03T16:39:08.986+08:00</updated><title type='text'>使用 GSM LIB 发送中文短信</title><content type='html'>这也是我早些年写的一个文章,这里面用的email地址因为每年都需要收费,不交费就停,这点钱到算不了什么关键是交起来太麻烦,忘了交就给我停了,后来就干脆不用了,有了gmail就更不需要了,但是地震一下感到还得使用本土的服务比较可靠. 呵呵.&lt;br /&gt;&lt;br /&gt;使用GSMlib发送中文短信&lt;br /&gt;           dingguijin@21cn.com&lt;br /&gt;GSMlib是访问GSM modem的库, 因此能访问相应的mobile phone. 它的主站点:&lt;br /&gt;&lt;a href="http://www.pxh.de/fs/gsmlib/" target="_blank"&gt;http://www.pxh.de/fs/gsmlib/&lt;/a&gt;&lt;br /&gt;如果你有如下之一的设备, 那么你就可以通过串口或者红外基于GSMlib来控制你的设备.&lt;br /&gt;&amp;#8226; Nokia 6150/Xircom REM56G.100 &lt;br /&gt;&amp;#8226; Nokia 6150/Options "GSM-Ready(R) Cellular-Only" modem from Option International &lt;br /&gt;&amp;#8226; Nokia 8810/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Siemens S10D/Dr Neuhaus Gipsy Card GSM &lt;br /&gt;&amp;#8226; Siemens S25/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Siemens S35i/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Ericcson SH888/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Ericsson 6050102/GM 12 GSM module &lt;br /&gt;&amp;#8226; Siemens M20T/- (stand-alone GSM module) &lt;br /&gt;&amp;#8226; Wavecom WM02 GSM/- (stand-alone GSM module) &lt;br /&gt;&amp;#8226; Nokia 7110 (firware rev 4.80)/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Nokia 8290 (USA GSM 1900MHz)/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Falcom A2-1/- (stand-alone GSM module) &lt;br /&gt;&amp;#8226; Ericsson R320s/- (Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Motorola Timeport 260/- (Serial cable and Linux IrDA serial device) &lt;br /&gt;&amp;#8226; Motorola Timeport 250/- (Linux IrDA serial device) &lt;br /&gt;在这里面我用过Wavecom WM02 的GSM modem, 成功发送中文短信.&lt;br /&gt;由于在短信息中对于多字节字符采用的是Unicode 编码(编码的意思就是 文字的数据形式, 文字是人可以阅读的; 而计算机, 网络传输使用的是数据, 进行通讯的设备达成一个统一, 说0xbb 0xcc 表示某某一个文字, 其中有一种统一叫做Unicode, 叫这个名字的原因是它自认为懂得全世界的语言, 简体中文和繁体中文的文字的相当一部分被包含进来了, 所以手机上的文字是简体繁体可以同在一起显示, 不象桌面计算机了), 而在一般的桌面机器上的简体汉字都是GB2312的编码, 所以我们把它转成Unicode, 在linux中叫做multi char to wide char&lt;br /&gt;多字节字转成宽字节字, 然后再将宽字转成网络顺序, 发送OK. 简单的过程也有几个陷阱.这是我的发送程序, 使用串口连接的wavecom 的 GSM modem.&lt;br /&gt;try {&lt;br /&gt;               // handle command line options&lt;br /&gt;    // 你的设备连接到了什么上&lt;br /&gt;               string device = "/dev/ttyS0";&lt;br /&gt;    //速率是多少&lt;br /&gt;               string baudrate = "19200";&lt;br /&gt;               string initString = DEFAULT_INIT_STRING;&lt;br /&gt;    //你想发给谁?&lt;br /&gt;               string phoneNumber = “13910180xxx”;&lt;br /&gt;               bool swHandshake = false;&lt;br /&gt;               bool requestStatusReport = false;&lt;br /&gt;    //这是断消息中心&lt;br /&gt;               string serviceCentreAddress = "+8613800100500";&lt;br /&gt;    &lt;br /&gt;   //发送的内容&lt;br /&gt;    char    gbc[200] = “我们都是神枪手”;&lt;br /&gt;               wchar_t utf8c[100];&lt;br /&gt;               int  wcsize;&lt;br /&gt;               int     i;&lt;br /&gt;&lt;br /&gt;//下面的这个函数是依赖你的locale的设定的, 这样它就知道原始的编码是什么了&lt;br /&gt;//当然也可以在程序中显示的设置locale为zh_CN.GB2312&lt;br /&gt;               mbstowcs(utf8c, gbc, strlen(gbc));&lt;br /&gt;               wcsize = wcslen(utf8c);&lt;br /&gt;               string text;&lt;br /&gt;               for(i = 0; i &lt; wcsize; i++) {&lt;br /&gt;                       utf8c[i] = htons(utf8c[i]);&lt;br /&gt;//只用插入才能是wchar_t的东西放到string类的对象中, 因为直接赋值, 会有零, 你于是只能发送一个汉字. 在C++中也有wstring 不过gsmlib没有用它呀&lt;br /&gt;                       text.insert(2*i, (char*)&amp;utf8c[i], 2);&lt;br /&gt;               }&lt;br /&gt;&lt;br /&gt;               Ref&lt;gsmat&gt; at;&lt;br /&gt;               // open the port and ME/TA&lt;br /&gt;               Ref&lt;port&gt; port = new UnixSerialPort (device, baudRateStrToSpeed(baudrate), initString, swHandshake);&lt;br /&gt;               // switch message service level to 1&lt;br /&gt;               // this enables acknowledgement PDUs&lt;br /&gt;               MeTa m(port);&lt;br /&gt;&lt;br /&gt;               m.setMessageService(1);&lt;br /&gt;               at = new GsmAt(m);&lt;br /&gt;               // send SMS&lt;br /&gt;               Ref&lt;smssubmitmessage&gt; submitSMS = new SMSSubmitMessage(text, phoneNumber);&lt;br /&gt;               // set service centre address in new submit PDU if requested by user&lt;br /&gt;               submitSMS-&gt;setDataCodingScheme(DataCodingScheme(DCS_SIXTEEN_BIT_ALPHABET));&lt;br /&gt;               //submitSMS-&gt;setUserData(text);&lt;br /&gt;               Address sca(serviceCentreAddress);&lt;br /&gt;               submitSMS-&gt;setServiceCentreAddress(sca);&lt;br /&gt;               submitSMS-&gt;setStatusReportRequest(requestStatusReport);&lt;br /&gt;               submitSMS-&gt;setAt(at);&lt;br /&gt;&lt;br /&gt;               Ref&lt;smsmessage&gt; ackPDU;&lt;br /&gt;               submitSMS-&gt;send(ackPDU);&lt;br /&gt;               // print acknowledgement if available&lt;br /&gt;               if (! ackPDU.isnull())&lt;br /&gt;                       cout &lt;&lt;&gt;toString();&lt;br /&gt;       } catch (GsmException &amp;ge) {&lt;br /&gt;               cerr &lt;&lt; argv[0] &lt;&lt; _("[ERROR]: ") &lt;&lt; ge.what() &lt;&lt; endl;&lt;br /&gt;               exit(1);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Makefile 里面要连接正确的库, 我没有把gsmlib安装, 只编译了一下.&lt;br /&gt;all:    smsd smssend&lt;br /&gt;&lt;br /&gt;gsmlibdir = /root/gsmlib-1.9&lt;br /&gt;gsmliblibsdir = $(gsmlibdir)/gsmlib/.libs&lt;br /&gt;&lt;br /&gt;cflags = -c -g -Wall  -I $(gsmlibdir)&lt;br /&gt;ldflags = --static -L $(gsmliblibsdir) -lgsmme&lt;br /&gt;&lt;br /&gt;smsd_objs = smsd.o&lt;br /&gt;smssend_objs = smssend.o&lt;br /&gt;&lt;br /&gt;smsd : $(smsd_objs)&lt;br /&gt;       g++ $(ldfalgs) -o $@ $^ $(ldflags)&lt;br /&gt;smssend : $(smssend_objs)&lt;br /&gt;       g++ $(ldfalgs) -o $@ $^ $(ldflags)&lt;br /&gt;%.o:%.cc&lt;br /&gt;       g++ $(cflags) $&lt;&lt;br /&gt;&lt;br /&gt;.PHONY:clean&lt;br /&gt;clean:&lt;br /&gt;       rm -f *~ *.o smsd smssend core&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-6170371626131600219?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/6170371626131600219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=6170371626131600219' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6170371626131600219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/6170371626131600219'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/gsm-lib.html' title='使用 GSM LIB 发送中文短信'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-652287674571376978</id><published>2007-01-03T16:30:00.000+08:00</published><updated>2007-01-03T16:34:25.846+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VOIP H323 SIP CTI'/><title type='text'>使用OpenH323开发VOIP程序</title><content type='html'>这是我早些年写的一片文章,当时花了挺多的时间,写了很多可是当时的LinuxByte不能一次上传 那么多内容导致现在网上流传的都是少了一部份的版本,那么现在我把它找回来,我这两天有时间把它补全,再看看OpenH323的工程有什么新的动向了,以前看OPAL说统一了H323和SIP的接口应该是个好事情,OpenH323的接口封装的还是非常漂亮的.&lt;br /&gt;&lt;br /&gt;必备软件包可以从&lt;a href="http://www.openh323.org/" target="_blank" style="color: rgb(0, 55, 147);"&gt;http://www.openh323.org&lt;/a&gt;下载. &lt;br /&gt;pwlib是一套跨平台的C++的开发库,使基于pwlib上开发的应用能够很少量的移植就可以跑在windows和unix的平台上.&lt;br /&gt;Open323是澳洲的一家公司驱动的open source的h323协议族实现, 还不够十分的完整, 但是已经是非常的难得了.&lt;br /&gt;在windows上和linux下都能编译使用, 我已经试过了. Windows上编译他们比较麻烦, 注意的是一定要用batch building. 在VC7上编译openh323的动态连接库的时候, VS.net会崩溃, 注意避开, 不过也可以试试看看现象, 如果能够解决, 请告诉我一下.&lt;br /&gt;在linux上编译就没有什么好说的了, 设好两个环境变量(PWLIBDIR, OPENH323DIR), 就可以在展开的目录下编译了, 先编译PWLIB, 再编译OPENH323, 别忘了将相应xx/lib写到/etc/ld.so.conf下. 我这里可能对安装讲的不够详细, openh323讲的非常详细, 大家可以去看.&lt;br /&gt;&lt;br /&gt;以linux平台为例:&lt;br /&gt;使用pwlib, 在成功编译之后, 到$(PWLIBDIR)/SAMPLES/&lt;br /&gt;这里是一些例子, hello_world 是个非常简单的工程, 从这里我们可以看到如何写使用pwlib的Makefile:&lt;br /&gt;# Simple makefile for the hello world program&lt;br /&gt;PROG    = hello&lt;br /&gt;SOURCES = hello.cxx&lt;br /&gt;ifndef PWLIBDIR&lt;br /&gt;PWLIBDIR=$(HOME)/pwlib&lt;br /&gt;endif&lt;br /&gt;include $(PWLIBDIR)/make/ptlib.mak&lt;br /&gt;关键是包含了一个ptlib.mak&lt;br /&gt;&lt;br /&gt;hello.cxx&lt;br /&gt;#include &lt;ptlib.h&gt;&lt;br /&gt;class Hello : public PProcess&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(Hello, PProcess)&lt;br /&gt;  public:&lt;br /&gt;    void Main();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;PCREATE_PROCESS(Hello)&lt;br /&gt;void Hello::Main()&lt;br /&gt;{&lt;br /&gt;  cout &lt;&lt; "Hello world!\n";&lt;br /&gt;}&lt;br /&gt;非常有代表性. Include $(PWLIBDIR)/make/ptlib.mak 这样就可以make all, make debug的之类的进行编译, 需要的头文件库都会替你安排好. 编译的结果就会放在obj_linux_x86_xx, xx 表示你用的是debug编译还是其他, 如果是debug, xx就是d.&lt;br /&gt;&lt;br /&gt;使用pwlib的程序, 必然要有一个PProcess的子类, 作为整个进程, 这是指在console模式下, gui模式的用PApplication这个我没有用过. Pwlib里面的类大多都是P开头, (可能是取其兼容的意思, 跨平台的特性, 我瞎猜的), 在进程中如果想创建新的线程就创建PThread子类的对象, 对于这种关于过程的类,都有Main函数等待子类去实现.&lt;br /&gt;在使用所有的P类的时候, 注意使用两个宏, 声明类的时候PCLASSINFO(Hello, PProcess); 分号可以加, 也可不加. PProcess的子类的实现的时候要用PCREATE_PROCESS(Hello);, 这个东西把main()之类的系统入口封装了, 由他来调用Main()成员函数. 在使用线程的时候, 如果想让线程从线程的对象一创建就运行, 就应该在PThread子类中的构造函数中调用父类的Resume(). 关于pwlib先说这些, 在使用Openh323的时候到处都会用到pwlib的东西和概念.&lt;br /&gt;&lt;br /&gt;Openh323:&lt;br /&gt;终于进入正题了, 先粗略的讲点概念(多余了), H323是指协议族了, 包含了很多规范, 它来自ITU, 应会议的需要而产生, 信令相关的东西用H225 H245,类似Q931,用ASN1编码后在tcp之上传输, 数据相关的就是编码解码的东西了(包括音频视频), 音频g711(alaw, ulaw)了等等多了, 视频h261, 好像h263还没实现.&lt;br /&gt; 在H323的系统里进行通讯的角色实体就是Endpoint, 每个Endpoint可以有很多的Connection, 每个Endpoint也可以拥有很多的逻辑角色, 这个不讨论.&lt;br /&gt; Endpoint 在Openh323中就是类H323Endpoint的实例&lt;br /&gt; Connection 在Openh323中就是 H323Connection的实例&lt;br /&gt;当Endpoint接收了一个远程的连接请求, Endpoint就会创建一个H323Connection;&lt;br /&gt;当Endpoint发出一个连接的请求, Endpoint也会创建一个H323Connection&lt;br /&gt;Connection 就会进入一个状态机, 在各个状态中, Connetcion会相应的执行相应的方法, 这些方法, 大多都是Onxxxxx(), 是虚函数, 我们可以自己通过继承H323Connection创建其子类, 并且在我们想做事的时机去重载相应的虚函数. 这是使用Openh323的一个基本的思路.&lt;br /&gt;现在我们可以看看如何写一个自己H323的Endpoint, 让它能够和netmeeting互操作.成功编译Openh323后在它的samples的目录下面有几个例子, mfc是指在windows下如何使用MFC和Openh323一起开发, 还有simple, 这是个简单的H323的Endpoint的实现, 作为理解OpenH323的库如何使用和开发的技巧方法已经足够了.&lt;br /&gt; 程序运行主线:&lt;br /&gt; PWLIB(PCREATE_PROCESS(SimpleH323Process))--SimpleH323Process:: SimpleH323Process()--SimpleH323Process::Main();&lt;br /&gt;Main()如果结束, 这个程序就结束了, 可是Main()里面有个死循环, 写过图形程序的朋友们都知道, 这就是在等消息来呀. 在VC中称之为Interface thread.&lt;br /&gt; 程序注解:&lt;br /&gt; main.h&lt;br /&gt; 这个文件包含了程序用到的所有类的声明, 一般应该至少有三个类:&lt;br /&gt; 来自PProcess的一个主进程的, 或者说作为界面线程的;(只有一个对象)&lt;br /&gt; 来自H323Endpoint的, 标识这个H323端点的;(只有一个对象)&lt;br /&gt; 来自H323Connection的, 标识所有和这个H323端点相关的连接;(可以有多个)&lt;br /&gt;&lt;br /&gt;#ifndef _SimpleH323_MAIN_H&lt;br /&gt;#define _SimpleH323_MAIN_H&lt;br /&gt;//避免头文件重复包含&lt;br /&gt;&lt;br /&gt;#include &lt;h323.h&gt;&lt;br /&gt;&lt;br /&gt;class SimpleH323EndPoint : public H323EndPoint&lt;br /&gt;{ &lt;br /&gt;//使用Pwlib的要求, 就像使用MFC, 有n多的宏, 可以看看pwlib的源码,&lt;br /&gt;//宏展开都干了什么&lt;br /&gt;  PCLASSINFO(SimpleH323EndPoint, H323EndPoint);&lt;br /&gt;  &lt;br /&gt;  public:&lt;br /&gt;    SimpleH323EndPoint();&lt;br /&gt;    ~SimpleH323EndPoint();&lt;br /&gt;    &lt;br /&gt;// overrides from H323EndPoint&lt;br /&gt;// 重载H323EndPoint的函数&lt;br /&gt;&lt;br /&gt;// 当收到一个远程的呼入和发出呼出的请求的时候&lt;br /&gt;virtual H323Connection * CreateConnection(unsigned callReference);&lt;br /&gt;// 有远程的请求来到, 这是在CreateConnection之后的&lt;br /&gt;virtual BOOL OnIncomingCall(H323Connection &amp;, const H323SignalPDU &amp;amp;, H323SignalPDU &amp;);&lt;br /&gt;//应答远程的呼入&lt;br /&gt;virtual H323Connection::AnswerCallResponse OnAnswerCall(H323Connection &amp;, const PString &amp;amp;, const H323SignalPDU &amp;, H323SignalPDU&lt;br /&gt;&amp;amp;); &lt;br /&gt; //当连接被Forward&lt;br /&gt;virtual BOOL OnConnectionForwarded(H323Connection &amp;, const PString &amp;amp;, const H323SignalPDU &amp;);&lt;br /&gt;//当连接建立&lt;br /&gt;virtual void OnConnectionEstablished(H323Connection &amp; connection, const PString &amp;amp; token);&lt;br /&gt;//当连接撤销&lt;br /&gt;virtual void OnConnectionCleared(H323Connection &amp; connection, const PString &amp;amp; clearedCallToken);&lt;br /&gt;//当连接需要打开声音的通道&lt;br /&gt;    virtual BOOL OpenAudioChannel(H323Connection &amp;, BOOL, unsigned, H323AudioCodec &amp;amp;);&lt;br /&gt;    &lt;br /&gt;// New functions&lt;br /&gt;// 自己添加的新函数, 父类中不存在&lt;br /&gt;    BOOL Initialise(PArgList &amp;); &lt;br /&gt;    BOOL SetSoundDevice(PArgList &amp;, const char *, PSoundChannel::Directions);&lt;br /&gt;    // 每个连接会有一个Token来唯一标识&lt;br /&gt;    PString currentCallToken;&lt;br /&gt;  &lt;br /&gt;  protected:&lt;br /&gt;    BOOL autoAnswer;&lt;br /&gt;    PString busyForwardParty;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class SimpleH323Connection : public H323Connection&lt;br /&gt;{   &lt;br /&gt;    PCLASSINFO(SimpleH323Connection, H323Connection);&lt;br /&gt;  &lt;br /&gt;  public:&lt;br /&gt; //创建连接对象的时候将Endpoint的对象以引用传进来&lt;br /&gt; //引用的概念就是将整个对象暴露给你的意思, 不是复制了一份的意思,&lt;br /&gt;//对象还是原来的对象, 所以在Connection中修改了EndPoint的某些属性后&lt;br /&gt;//就是在操作着传进来的对象, 这是C++的基本概念, OpenH323大量的使用&lt;br /&gt;//引用传递对象, 对引用的概念要理解&lt;br /&gt;    SimpleH323Connection(SimpleH323EndPoint &amp;, unsigned);&lt;br /&gt;    &lt;br /&gt;//重载了两个父类的函数&lt;br /&gt;&lt;br /&gt;// 当打开逻辑通道的时候(等于没说)&lt;br /&gt;virtual BOOL OnStartLogicalChannel(H323Channel &amp;);&lt;br /&gt;// 处理用户输入, 这个不是之运行这个程序的用户,而是这个连接上的用户输入&lt;br /&gt;// 一般应该是拨号了之类的, &lt;br /&gt;    virtual void OnUserInputString(const PString &amp;);&lt;br /&gt;  &lt;br /&gt;  protected:&lt;br /&gt; // 快速连接??&lt;br /&gt;    BOOL noFastStart;&lt;br /&gt;};&lt;br /&gt;class SimpleH323Process : public PProcess&lt;br /&gt;{ &lt;br /&gt;//主进程, 类似VC的用户界面线程,&lt;br /&gt;//他是整个程序的入口点, 和结束点&lt;br /&gt;//创建了EndPoint对象后会有好几个线程启动&lt;br /&gt;//这个就是主线程&lt;br /&gt;  PCLASSINFO(SimpleH323Process, PProcess)&lt;br /&gt;  &lt;br /&gt;  public:&lt;br /&gt;    SimpleH323Process();&lt;br /&gt;    ~SimpleH323Process();&lt;br /&gt;//这个函数会被自动调用, 是我们程序的入口了&lt;br /&gt;    void Main();&lt;br /&gt;  protected:&lt;br /&gt;&lt;br /&gt;//这个H323端点对象&lt;br /&gt;    SimpleH323EndPoint * endpoint;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif  // _SimpleH323_MAIN_H&lt;br /&gt;&lt;br /&gt;下面是main.cpp 所有的类的实现了&lt;br /&gt;&lt;br /&gt;#include &lt;ptlib.h&gt;&lt;br /&gt;&lt;br /&gt;#ifdef __GNUC__&lt;br /&gt;#define H323_STATIC_LIB&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;#include "main.h"&lt;br /&gt;#include "../../version.h"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#define new PNEW&lt;br /&gt;&lt;br /&gt;// 这个东西里边可能封装了标准的main函数&lt;br /&gt;PCREATE_PROCESS(SimpleH323Process);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;//几个宏都在version.h里面定义&lt;br /&gt;SimpleH323Process::SimpleH323Process()&lt;br /&gt;  : PProcess("OpenH323 Project", "SimpleH323",&lt;br /&gt;             MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)&lt;br /&gt;{&lt;br /&gt;  endpoint = NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SimpleH323Process::~SimpleH323Process()&lt;br /&gt;{&lt;br /&gt;  delete endpoint;&lt;br /&gt;}&lt;br /&gt;void SimpleH323Process::Main()&lt;br /&gt;{&lt;br /&gt;        cout &lt;&lt; GetName()&lt;br /&gt;             &lt;&lt; " Version " &lt;&lt; GetVersion(TRUE)&lt;br /&gt;             &lt;&lt; " by " &lt;&lt; GetManufacturer()&lt;br /&gt;             &lt;&lt; " on " &lt;&lt; GetOSClass() &lt;&lt;   &lt;&lt; GetOSName()&lt;br /&gt;             &lt;&lt; " (" &lt;&lt; GetOSVersion() &lt;&lt; - &lt;&lt; GetOSHardware() &lt;&lt; ")\n\n";&lt;br /&gt;&lt;br /&gt;        // Get and parse all of the command line arguments.&lt;br /&gt;  // 分析命令行参数, 略去数行&lt;br /&gt;        PArgList &amp; args = GetArguments();&lt;br /&gt;        args.Parse(&lt;br /&gt;                "a-auto-answer."&lt;br /&gt;                "b-bandwidth:"&lt;br /&gt;                "B-forward-busy:"&lt;br /&gt;                "D-disable:” FALSE);&lt;br /&gt;        if (args.HasOption(h) || (!args.HasOption(l) &amp;&amp;amp; args.GetCount() == 0)) {&lt;br /&gt;  //如果没有参数或者参数是h, 就输出如何使用, 此处略去数行&lt;br /&gt;}&lt;br /&gt;//这个东西暂时不管&lt;br /&gt;#if PTRACING&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;// Create the H.323 endpoint and initialise it&lt;br /&gt;// H323 EndPoint 创建了, 并且把命令参数传过去初始化, 初始化的时候做了一些事&lt;br /&gt;endpoint = new SimpleH323EndPoint;&lt;br /&gt;if (!endpoint-&gt;Initialise(args))&lt;br /&gt;        return;&lt;br /&gt;//看看命令行里是不是想直接呼叫另一个H323的endpoint.有没有l(listen)的option&lt;br /&gt;//如果是就MakeCall, &lt;br /&gt;// See if making a call or just listening.&lt;br /&gt;        if (args.HasOption(l))&lt;br /&gt;                cout &lt;&lt; "Waiting for incoming calls for \"" &lt;&lt;&gt;GetLocalUserName() &lt;&lt; "\"\n";&lt;br /&gt;        else {&lt;br /&gt;                cout &lt;&lt; "Initiating call to \"" &lt;&lt; args[0] &lt;&lt; "\"\n";&lt;br /&gt;                endpoint-&gt;MakeCall(args[0], endpoint-&gt;currentCallToken);&lt;br /&gt;        }&lt;br /&gt;        cout &lt;&lt; "Press X to exit." &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;        // Simplest possible user interface&lt;br /&gt;  // 简单的用户界面, 会有一个提示&gt;&lt;br /&gt;  // 取pid是我加的&lt;br /&gt;        for (;;) {&lt;br /&gt;                pid_t thispid;&lt;br /&gt;                char prom[20];&lt;br /&gt;&lt;br /&gt;                thispid = getpid();&lt;br /&gt;                sprintf(prom, "H323 %d &gt;", thispid);&lt;br /&gt;&lt;br /&gt;                cout &lt;&lt; prom &lt;&lt; flush;&lt;br /&gt;    PCaselessString cmd;&lt;br /&gt;    cin &gt;&gt; cmd;&lt;br /&gt;    if (cmd == "X")&lt;br /&gt;      break;&lt;br /&gt;&lt;br /&gt;    if (cmd.FindOneOf("HYN") != P_MAX_INDEX) {&lt;br /&gt;      H323Connection*connection;&lt;br /&gt;//使用lock就是怕别的线程把它给删了&lt;br /&gt;//因为这里正用着呢&lt;br /&gt;connection=endpoint-&gt;FindConnectionWithLock(endpoint-&gt;currentCallToken);&lt;br /&gt;      if (connection != NULL) {&lt;br /&gt;        if (cmd == "H")&lt;br /&gt;          connection-&gt;ClearCall();&lt;br /&gt;        else if (cmd == "Y")&lt;br /&gt;          connection-&gt;AnsweringCall(H323Connection::AnswerCallNow);&lt;br /&gt;        else if (cmd == "N")&lt;br /&gt;          connection-&gt;AnsweringCall(H323Connection::AnswerCallDenied);&lt;br /&gt;        connection-&gt;Unlock();&lt;br /&gt;      }&lt;br /&gt;}&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Exiting " &lt;&lt; GetName() &lt;&lt; endl;&lt;br /&gt;}&lt;br /&gt;// Main 函数结束&lt;br /&gt;&lt;br /&gt;// 自己的Init函数&lt;br /&gt;BOOL SimpleH323EndPoint::Initialise(PArgList &amp; args)&lt;br /&gt;{&lt;br /&gt;  // Get local username, multiple uses of -u indicates additional aliases&lt;br /&gt;  if (args.HasOption(u)) {&lt;br /&gt;    PStringArray aliases = args.GetOptionString(u).Lines();&lt;br /&gt; // 设定改Endpoint的username&lt;br /&gt;    SetLocalUserName(aliases[0]);&lt;br /&gt; // 设定Aliases 就是每个Endpoint可以有好多名字的意思&lt;br /&gt;    for (PINDEX i = 1; i &lt; aliases.GetSize(); i++)&lt;br /&gt;      AddAliasName(aliases[i]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Set the various options&lt;br /&gt;  //设置静音检测否&lt;br /&gt; &lt;br /&gt;  SetSilenceDetectionMode(args.HasOption(e) ? H323AudioCodec::NoSilenceDetection&lt;br /&gt;                                              : H323AudioCodec::AdaptiveSilenceDetection);&lt;br /&gt;//快速连接? &lt;br /&gt; DisableFastStart(args.HasOption(f));&lt;br /&gt;//H245通道  &lt;br /&gt;DisableH245Tunneling(args.HasOption(T));&lt;br /&gt;&lt;br /&gt;  autoAnswer           = args.HasOption(a);&lt;br /&gt;  busyForwardParty     = args.GetOptionString(B);&lt;br /&gt;&lt;br /&gt;  if (args.HasOption()) {&lt;br /&gt;    initialBandwidth = args.GetOptionString().AsUnsigned()*100;&lt;br /&gt;    if (initialBandwidth == 0) {&lt;br /&gt;      cerr &lt;&lt; "Illegal bandwidth specified." &lt;&lt; endl;&lt;br /&gt;      return FALSE;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (args.HasOption(j)) {&lt;br /&gt;    unsigned jitter = args.GetOptionString(j).AsUnsigned();&lt;br /&gt; //设定音频抖动的, 应该影响到接收的缓存&lt;br /&gt;    if (jitter &gt;= 20 &amp;&amp;amp; jitter &lt;= 10000)&lt;br /&gt;      SetMaxAudioDelayJitter(jitter);&lt;br /&gt;    else {&lt;br /&gt;      cerr &lt;&lt; "Jitter should be between 20 milliseconds and 10 seconds." &lt;&lt; endl;&lt;br /&gt;      return FALSE;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; //设定声音设备&lt;br /&gt; //也可以不用声音设备, 比如Openh323工程的子项目 OpenAM和OpenMCU&lt;br /&gt; //都使演示了如何不使用声音物理设备的方法, 我想那里边的东西会对某些朋友们&lt;br /&gt; //的需求比较合适&lt;br /&gt;  if (!SetSoundDevice(args, "sound", PSoundChannel::Recorder))&lt;br /&gt;    return FALSE;&lt;br /&gt;  if (!SetSoundDevice(args, "sound", PSoundChannel::Player))&lt;br /&gt;    return FALSE;&lt;br /&gt;  if (!SetSoundDevice(args, "sound-in", PSoundChannel::Recorder))&lt;br /&gt;    return FALSE;&lt;br /&gt;  if (!SetSoundDevice(args, "sound-out", PSoundChannel::Player))&lt;br /&gt;    return FALSE;&lt;br /&gt;&lt;br /&gt; // 设定decode encode的能力&lt;br /&gt; // H323 EndPoint在真正进行数据通讯之前要进行能力的交换, 说明自己能够接收和发送什么标准的数据, g.711是必须支持的.&lt;br /&gt;  // Set the default codecs available on sound cards.&lt;br /&gt;  AddAllCapabilities(0, 0, "GSM*{sw}");&lt;br /&gt;  AddAllCapabilities(0, 0, "G.711*{sw}");&lt;br /&gt;  AddAllCapabilities(0, 0, "LPC*{sw}");&lt;br /&gt;  AddAllUserInputCapabilities(0, 1);&lt;br /&gt;&lt;br /&gt;  RemoveCapabilities(args.GetOptionString(D).Lines());&lt;br /&gt;  ReorderCapabilities(args.GetOptionString(P).Lines());&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Local username: " &lt;&lt; GetLocalUserName() &lt;&lt; "\n"&lt;br /&gt;&lt;&lt; "Silence compression is " &lt;&lt; (GetSilenceDetectionMode() == H323AudioCodec::NoSilenceDetection ? "Dis" : "En") &lt;&lt; "abled\n"&lt;br /&gt;       &lt;&lt; "Auto answer is " &lt;&lt; autoAnswer &lt;&lt; "\n"&lt;br /&gt;       &lt;&lt; "FastConnect is " &lt;&lt; (IsFastStartDisabled() ? "Dis" : "En") &lt;&lt; "abled\n"&lt;br /&gt;       &lt;&lt; "H245Tunnelling is " &lt;&lt; (IsH245TunnelingDisabled() ? "Dis" : "En") &lt;&lt; "abled\n"&lt;br /&gt;       &lt;&lt; "Jitter buffer: "  &lt;&lt; GetMaxAudioDelayJitter() &lt;&lt; " ms\n"&lt;br /&gt;       &lt;&lt; "Sound output device: \"" &lt;&lt; GetSoundChannelPlayDevice() &lt;&lt; "\"\n"&lt;br /&gt;          "Sound  input device: \"" &lt;&lt; GetSoundChannelRecordDevice() &lt;&lt; "\"\n"&lt;br /&gt;       &lt;&lt;  "Codecs (in preference order):\n" &lt;&lt; setprecision(2) &lt;&lt; GetCapabilities() &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;//启动一个来电的监听&lt;br /&gt;//可以使用配置的端口, 也可以使用default的端口&lt;br /&gt;  // Start the listener thread for incoming calls.&lt;br /&gt;  H323ListenerTCP * listener;&lt;br /&gt;  if (args.GetOptionString(i).IsEmpty())&lt;br /&gt;    listener  = new H323ListenerTCP(*this);&lt;br /&gt;  else {&lt;br /&gt;    PIPSocket::Address interfaceAddress(args.GetOptionString(i));&lt;br /&gt;    listener  = new H323ListenerTCP(*this, interfaceAddress);&lt;br /&gt;  }&lt;br /&gt;  if (!StartListener(listener)) {&lt;br /&gt;    cerr &lt;&lt;  "Could not open H.323 listener port on "&lt;br /&gt;         &lt;&lt;&gt;GetListenerPort() &lt;&lt; endl;&lt;br /&gt;    delete listener;&lt;br /&gt;    return FALSE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;//这是连接GateKeeper相关的东西, 先不讨论了&lt;br /&gt;  // Initialise the security info&lt;br /&gt;  if (args.HasOption(p)) {&lt;br /&gt;    SetGatekeeperPassword(args.GetOptionString(p));&lt;br /&gt;    cout &lt;&lt; "Enabling H.235 security access to gatekeeper." &lt;&lt; endl;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Establish link with gatekeeper if required.&lt;br /&gt;  if (args.HasOption(g) || !args.HasOption( )) {&lt;br /&gt;    H323TransportUDP * rasChannel;&lt;br /&gt;    if (args.GetOptionString(i).IsEmpty())&lt;br /&gt;      rasChannel  = new H323TransportUDP(*this);&lt;br /&gt;    else {&lt;br /&gt;      PIPSocket::Address interfaceAddress(args.GetOptionString(i));&lt;br /&gt;   rasChannel  = new H323TransportUDP(*this, interfaceAddress);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (args.HasOption(g)) {&lt;br /&gt;      PString gkName = args.GetOptionString(g);&lt;br /&gt;      if (SetGatekeeper(gkName, rasChannel))&lt;br /&gt;        cout &lt;&lt; "Gatekeeper set: " &lt;&lt; *gatekeeper &lt;&lt; endl;&lt;br /&gt;      else {&lt;br /&gt;        cerr &lt;&lt; "Error registering with gatekeeper at \"" &lt;&lt; gkName &lt;&lt; \" &lt;&lt; endl;&lt;br /&gt;        return FALSE;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      cout &lt;&lt; "Searching for gatekeeper..." &lt;&lt; flush;&lt;br /&gt;      if (DiscoverGatekeeper(rasChannel))&lt;br /&gt;        cout &lt;&lt; "\nGatekeeper found: " &lt;&lt; *gatekeeper &lt;&lt; endl;&lt;br /&gt;      else {&lt;br /&gt;        cerr &lt;&lt; "\nNo gatekeeper found." &lt;&lt; endl;&lt;br /&gt;        if (args.HasOption( ))&lt;br /&gt;          return FALSE;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//设定音频设备, 没什么可讲的&lt;br /&gt;BOOL SimpleH323EndPoint::SetSoundDevice(PArgList &amp; args,&lt;br /&gt;                                        const char * optionName,&lt;br /&gt;                                        PSoundChannel::Directions dir)&lt;br /&gt;{&lt;br /&gt;  if (!args.HasOption(optionName))&lt;br /&gt;    return TRUE;&lt;br /&gt;&lt;br /&gt;  PString dev = args.GetOptionString(optionName);&lt;br /&gt;&lt;br /&gt;  if (dir == PSoundChannel::Player) {&lt;br /&gt;    if (SetSoundChannelPlayDevice(dev))&lt;br /&gt;      return TRUE;&lt;br /&gt;  }&lt;br /&gt;  else {&lt;br /&gt;    if (SetSoundChannelRecordDevice(dev))&lt;br /&gt;      return TRUE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cerr &lt;&lt; "Device for " &lt;&lt; optionName &lt;&lt; " (\"" &lt;&lt; dev &lt;&lt; "\") must be one of:\n";&lt;br /&gt;&lt;br /&gt;  PStringArray names = PSoundChannel::GetDeviceNames(dir);&lt;br /&gt;  for (PINDEX i = 0; i &lt; names.GetSize(); i++)&lt;br /&gt;    cerr &lt;&lt; "  \"" &lt;&lt; names[i] &lt;&lt; "\"\n";&lt;br /&gt;&lt;br /&gt;  return FALSE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//这个函数很简单但是非常关键, 是从EndPoint中重载过来的.&lt;br /&gt;//本来是return new H323Connection()的, 现在改成Simplexxx&lt;br /&gt;//自己实现的一个Connection, 这样当Endpoint里面调用&lt;br /&gt;//Connection的一些东西的时候, 实际上运行的是Simplexxx&lt;br /&gt;//的实现, 看到C++的好处了吧, C里用函数指针也可以实现, 没有&lt;br /&gt;//C++这么native.&lt;br /&gt;H323Connection * SimpleH323EndPoint::CreateConnection(unsigned callReference)&lt;br /&gt;{&lt;br /&gt;  return new SimpleH323Connection(*this, callReference);&lt;br /&gt;}&lt;br /&gt;//没什么东西, 关键是看看这个东西的调用的时机&lt;br /&gt;BOOL SimpleH323EndPoint::OnIncomingCall(H323Connection &amp; connection,&lt;br /&gt;                                        const H323SignalPDU &amp;amp;,&lt;br /&gt;                                        H323SignalPDU &amp;)&lt;br /&gt;{&lt;br /&gt;  if (currentCallToken.IsEmpty())&lt;br /&gt;    return TRUE;&lt;br /&gt;&lt;br /&gt;  if (busyForwardParty.IsEmpty()) {&lt;br /&gt;cout &lt;&lt; "Incoming call from \"" &lt;&lt; connection.GetRemotePartyName() &lt;&lt; "\" rejected, line busy!" &lt;&lt; endl;&lt;br /&gt;    return FALSE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Forwarding call to \"" &lt;&lt; busyForwardParty &lt;&lt; "\"." &lt;&lt; endl;&lt;br /&gt;  return !connection.ForwardCall(busyForwardParty);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//这个东西, 很有用, H323Connection的类里也有这个虚函数&lt;br /&gt;//返回的值决定告诉远程的连接者是否接收这份连接请求&lt;br /&gt;H323Connection::AnswerCallResponse&lt;br /&gt;                   SimpleH323EndPoint::OnAnswerCall(H323Connection &amp; connection,&lt;br /&gt;                                                    const PString &amp;amp; caller,&lt;br /&gt;                                                    const H323SignalPDU &amp;,&lt;br /&gt;                                                    H323SignalPDU &amp;amp;)&lt;br /&gt;{&lt;br /&gt;  currentCallToken = connection.GetCallToken();&lt;br /&gt;&lt;br /&gt;  if (autoAnswer) {&lt;br /&gt;    cout &lt;&lt; "Automatically accepting call." &lt;&lt; endl;&lt;br /&gt;    return H323Connection::AnswerCallNow;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Incoming call from \""&lt;br /&gt;       &lt;&lt; caller&lt;br /&gt;       &lt;&lt; "\", answer call (Y/n)? "&lt;br /&gt;       &lt;&lt; flush;&lt;br /&gt;&lt;br /&gt;  return H323Connection::AnswerCallPending;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL SimpleH323EndPoint::OnConnectionForwarded(H323Connection &amp; /*connection*/,&lt;br /&gt;                                               const PString &amp;amp; forwardParty,&lt;br /&gt;                                               const H323SignalPDU &amp; /*pdu*/)&lt;br /&gt;{&lt;br /&gt;  if (MakeCall(forwardParty, currentCallToken)) {&lt;br /&gt;    cout &lt;&lt; "Call is being forwarded to host " &lt;&lt; forwardParty &lt;&lt; endl;&lt;br /&gt;    return TRUE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Error forwarding call to \"" &lt;&lt; forwardParty &lt;&lt; \" &lt;&lt; endl;&lt;br /&gt;  return FALSE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//连接建立时候&lt;br /&gt;void SimpleH323EndPoint::OnConnectionEstablished(H323Connection &amp; connection,&lt;br /&gt;                                                 const PString &amp;amp; token)&lt;br /&gt;{&lt;br /&gt;  currentCallToken = token;&lt;br /&gt;  cout &lt;&lt; "In call with " &lt;&lt; connection.GetRemotePartyName() &lt;&lt; endl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//连接断开时候&lt;br /&gt;void SimpleH323EndPoint::OnConnectionCleared(H323Connection &amp; connection,&lt;br /&gt;                                             const PString &amp;amp; clearedCallToken)&lt;br /&gt;{&lt;br /&gt;  if (currentCallToken == clearedCallToken)&lt;br /&gt;    currentCallToken = PString();&lt;br /&gt;&lt;br /&gt;  PString remoteName = \" + connection.GetRemotePartyName() + \";&lt;br /&gt;  switch (connection.GetCallEndReason()) {&lt;br /&gt;    case H323Connection::EndedByRemoteUser :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " has cleared the call";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByCallerAbort :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " has stopped calling";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByRefusal :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " did not accept your call";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByNoAnswer :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " did not answer your call";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByTransportFail :&lt;br /&gt;      cout &lt;&lt; "Call with " &lt;&lt; remoteName &lt;&lt; " ended abnormally";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByCapabilityExchange :&lt;br /&gt;      cout &lt;&lt; "Could not find common codec with " &lt;&lt; remoteName;&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByNoAccept :&lt;br /&gt;      cout &lt;&lt; "Did not accept incoming call from " &lt;&lt; remoteName;&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByAnswerDenied :&lt;br /&gt;      cout &lt;&lt; "Refused incoming call from " &lt;&lt; remoteName;&lt;br /&gt;     break;&lt;br /&gt;    case H323Connection::EndedByNoUser :&lt;br /&gt;      cout &lt;&lt; "Gatekeeper could find user " &lt;&lt; remoteName;&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByNoBandwidth :&lt;br /&gt;      cout &lt;&lt; "Call to " &lt;&lt; remoteName &lt;&lt; " aborted, insufficient bandwidth.";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByUnreachable :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " could not be reached.";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByHostOffline :&lt;br /&gt;      cout &lt;&lt; remoteName &lt;&lt; " is not online.";&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByNoEndPoint :&lt;br /&gt;      cout &lt;&lt; "No phone running for " &lt;&lt; remoteName;&lt;br /&gt;      break;&lt;br /&gt;    case H323Connection::EndedByConnectFail :&lt;br /&gt;      cout &lt;&lt; "Transport error calling " &lt;&lt; remoteName;&lt;br /&gt;      break;&lt;br /&gt;    default :&lt;br /&gt;      cout &lt;&lt; "Call with " &lt;&lt; remoteName &lt;&lt; " completed";&lt;br /&gt;  }&lt;br /&gt;  cout &lt;&lt; ", duration "&lt;br /&gt;       &lt;&lt; setprecision(0) &lt;&lt; setw(5)&lt;br /&gt;       &lt;&lt; (PTime() - connection.GetConnectionStartTime())&lt;br /&gt;       &lt;&lt; endl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//打开声音设备时候&lt;br /&gt;//isEncoding 表示编码吗&lt;br /&gt;//编码表示向外发送数据, 从声音设备读&lt;br /&gt;//解码表示从网络读出数据, 写到声音设备上&lt;br /&gt;//不同的方向的codec是不同的, 所以在这里有好多文章可以做&lt;br /&gt;//可以给codec attach上不同的channel根据isEncoding的值&lt;br /&gt;BOOL SimpleH323EndPoint::OpenAudioChannel(H323Connection &amp; connection,&lt;br /&gt;                                          BOOL isEncoding,&lt;br /&gt;                                          unsigned bufferSize,&lt;br /&gt;                                          H323AudioCodec &amp;amp; codec)&lt;br /&gt;{&lt;br /&gt;  if (H323EndPoint::OpenAudioChannel(connection, isEncoding, bufferSize, codec))&lt;br /&gt;    return TRUE;&lt;br /&gt;&lt;br /&gt;  cerr &lt;&lt; "Could not open sound device ";&lt;br /&gt;  if (isEncoding)&lt;br /&gt;    cerr &lt;&lt; GetSoundChannelRecordDevice();&lt;br /&gt;  else&lt;br /&gt;    cerr &lt;&lt; GetSoundChannelPlayDevice();&lt;br /&gt;  cerr &lt;&lt; " - Check permissions or full duplex capability." &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  return FALSE;&lt;br /&gt;}&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;EndPoint的实现分析完毕.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;H323Connection的实现, 这个Connection的实现太简单了.可能不足以说明问题&lt;br /&gt;我也没什么好说的了&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;SimpleH323Connection::SimpleH323Connection(SimpleH323EndPoint &amp; ep, unsigned ref)&lt;br /&gt;  : H323Connection(ep, ref)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;BOOL SimpleH323Connection::OnStartLogicalChannel(H323Channel &amp;amp; channel)&lt;br /&gt;{&lt;br /&gt;  if (!H323Connection::OnStartLogicalChannel(channel))&lt;br /&gt;    return FALSE;&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Started logical channel: ";&lt;br /&gt;&lt;br /&gt;  switch (channel.GetDirection()) {&lt;br /&gt;    case H323Channel::IsTransmitter :&lt;br /&gt;      cout &lt;&lt; "sending ";&lt;br /&gt;      break;&lt;br /&gt;&lt;br /&gt;    case H323Channel::IsReceiver :&lt;br /&gt;      cout &lt;&lt; "receiving ";&lt;br /&gt;      break;&lt;br /&gt;&lt;br /&gt;    default :&lt;br /&gt;      break;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; channel.GetCapability() &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void SimpleH323Connection::OnUserInputString(const PString &amp; value)&lt;br /&gt;{&lt;br /&gt;  cout &lt;&lt; "User input received: \"" &lt;&lt; value &lt;&lt; \" &lt;&lt; endl;&lt;br /&gt;}&lt;br /&gt;// End of File ///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;总结一下基本的过程就是创建一个H323Endpoint的对象endpoint, 创建对象后这个程序就有好多个小的线程被创建了.然后EndPoint开始监听来电, 之后判断是否直接呼叫另一个h323的Endpoint. 然后就是一个for循环, 判断标准的输入, 并通过当前的token来lock一个Connection, 每个连接会有唯一的一个token, lock的意思是说, 在被lock的期间是不能被释放的. 根据输入的字符决定对得到的连接做什么.&lt;br /&gt;&lt;br /&gt;OpenAM:&lt;br /&gt; 是个answer machine, 自动应答机, 或者是留言机. 实现的很简单, 里面对OpenH323使用的思路很有价值.&lt;br /&gt; ./openam –n –-g711message sample_message.wav&lt;br /&gt;这样运行, 用netmeeting 连接一下这个IP, netmeeting就会放一段简单的英语, 测测你的英语听力, 他在讲什么?&lt;br /&gt; 这个程序是一个支持多连接和并发连接的Endpoint, 但是他没有使用真正的声音设备, 放出的音从一个已有的wav文件中读出来, 远程用户的留言被录到一个文件里, 文件的名字表示了是什么时间录制的.&lt;br /&gt;    主要的思路是给在连接打开声音通道的时候, 根据isEncoding的值区别是录音还是放音,如果是录音, 将读文件的Channel附加在codec上, 相反写文件的Channel附件在codec上,注意这是两个codec.&lt;br /&gt; 这个东西给了我们一个方法, 如何使用文件IO来代替声音设备的IO来使用OpenH323.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;这是main.h&lt;br /&gt;&lt;br /&gt;#ifndef _Voxilla_MAIN_H&lt;br /&gt;#define _Voxilla_MAIN_H&lt;br /&gt;&lt;br /&gt;#include &lt;h323.h&gt;&lt;br /&gt;#include &lt;h323pdu.h&gt;&lt;br /&gt;#include &lt;h245.h&gt;&lt;br /&gt;#include &lt;gsmcodec.h&gt;&lt;br /&gt;#include &lt;lid.h&gt;&lt;br /&gt;&lt;br /&gt;#include &lt;ptclib&gt;&lt;br /&gt;#include &lt;ptclib&gt;&lt;br /&gt;&lt;br /&gt;//主进程&lt;br /&gt;class OpenAm : public PProcess&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(OpenAm, PProcess)&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    OpenAm();&lt;br /&gt;    ~OpenAm();&lt;br /&gt;&lt;br /&gt;    void Main();&lt;br /&gt;    void RecordFile(PArgList &amp; args);&lt;br /&gt;    void PlayFile(PArgList &amp; args);&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    long GetCodec(const PString &amp; codecname);&lt;br /&gt;    OpalLineInterfaceDevice * GetDevice(const PString &amp; device);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//H323 端点&lt;br /&gt;class MyH323EndPoint : public H323EndPoint&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(MyH323EndPoint, H323EndPoint);&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    MyH323EndPoint(unsigned callLimit,&lt;br /&gt;                   const PString &amp; runCmd,&lt;br /&gt;                   const PDirectory &amp;amp; dir,&lt;br /&gt;                   int flags);&lt;br /&gt;&lt;br /&gt;    // overrides from H323EndPoint&lt;br /&gt;    virtual H323Connection * CreateConnection(unsigned callReference);&lt;br /&gt;    BOOL OnIncomingCall(H323Connection &amp;, const H323SignalPDU &amp;amp;, H323SignalPDU &amp;);&lt;br /&gt;&lt;br /&gt;    // new functions&lt;br /&gt;    BOOL Initialise(PConfigArgs &amp; args);&lt;br /&gt;&lt;br /&gt;    PString    GetGSMOGM() const            { return gsmOgm; }&lt;br /&gt;    void       SetGSMOGM(const PString &amp; s) { gsmOgm = s; }&lt;br /&gt;&lt;br /&gt;    PString    GetG711OGM() const            { return g711Ogm; }&lt;br /&gt;    void       SetG711OGM(const PString &amp; s) { g711Ogm = s; }&lt;br /&gt;&lt;br /&gt;    PString    GetLPC10OGM() const            { return lpc10Ogm; }&lt;br /&gt;    void       SetLPC10OGM(const PString &amp; s) { lpc10Ogm = s; }&lt;br /&gt;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;    PString    GetSPEEXOGM() const            { return speexOgm; }&lt;br /&gt;    void       SetSPEEXOGM(const PString &amp; s) { speexOgm = s; }&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;    PString    GetG7231OGM() const            { return g7231Ogm; }&lt;br /&gt;    void       SetG7231OGM(const PString &amp; s) { g7231Ogm = s; }&lt;br /&gt;&lt;br /&gt;    unsigned   GetCallLimit() const { return callLimit; }&lt;br /&gt;    PString    GetRunCmd() const    { return runCmd; }&lt;br /&gt;    PDirectory GetDirectory() const { return dir; }&lt;br /&gt;&lt;br /&gt;    void       SetRecordWav(const BOOL rec){ recordWav = rec; }&lt;br /&gt;    BOOL       GetRecordWav() const        { return recordWav; }&lt;br /&gt;&lt;br /&gt;    enum {&lt;br /&gt;      DeleteAfterRecord = 0x01,&lt;br /&gt;      NoRecordG7231     = 0x02,&lt;br /&gt;      HangupAfterPlay   = 0x04&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    BOOL GetDeleteAfterRecord() const   { return flags &amp; DeleteAfterRecord; }&lt;br /&gt;    BOOL GetNoRecordG7231() const       { return flags &amp; NoRecordG7231; }&lt;br /&gt;    BOOL GetHangupAfterPlay() const     { return flags &amp; HangupAfterPlay; }&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    unsigned callLimit;&lt;br /&gt;    PString pcmOgm, g711Ogm, gsmOgm, lpc10Ogm, g7231Ogm, runCmd;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;    PString speexOgm;&lt;br /&gt;#endif&lt;br /&gt;    PDirectory dir;&lt;br /&gt;    int flags;&lt;br /&gt;    BOOL recordWav;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class PCM_RecordFile;&lt;br /&gt;class MyH323Connection;&lt;br /&gt;PQUEUE(PStringQueue, PString);&lt;br /&gt;// Out Going Channel OGM &lt;br /&gt;//就是发送语音的通道&lt;br /&gt;//即是读文件的通道&lt;br /&gt;class PCM_OGMChannel : public PIndirectChannel&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(PCM_OGMChannel, PIndirectChannel);&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    PCM_OGMChannel(MyH323Connection &amp; conn);&lt;br /&gt;&lt;br /&gt;    BOOL Read(void * buffer, PINDEX amount);&lt;br /&gt;    void PlayFile(PFile * chan);&lt;br /&gt;&lt;br /&gt;    BOOL Close();&lt;br /&gt;&lt;br /&gt;    void QueueFile(const PString &amp; cmd);&lt;br /&gt;    void FlushQueue();&lt;br /&gt;&lt;br /&gt;    void SetRecordTrigger();&lt;br /&gt;    void SetHangupTrigger();&lt;br /&gt;&lt;br /&gt;    void SetPlayOnce() { playOnce = TRUE; }&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    virtual BOOL ReadFrame(PINDEX amount);&lt;br /&gt;    virtual void CreateSilenceFrame(PINDEX amount);&lt;br /&gt;    virtual void Synchronise(PINDEX amount);&lt;br /&gt;    virtual BOOL IsWAVFileValid(PWAVFile *chan);&lt;br /&gt;&lt;br /&gt;    BOOL AdjustFrame(void * buffer, PINDEX amount);&lt;br /&gt;&lt;br /&gt;    PStringQueue playQueue;&lt;br /&gt;&lt;br /&gt;    MyH323Connection &amp; conn;&lt;br /&gt;    PMutex chanMutex;&lt;br /&gt;    int silentCount;&lt;br /&gt;    int totalData;&lt;br /&gt;    BOOL recordTrigger, hangupTrigger;&lt;br /&gt;    BOOL closed;&lt;br /&gt;    BOOL playOnce;&lt;br /&gt;&lt;br /&gt;    PAdaptiveDelay ogm_delay;&lt;br /&gt;&lt;br /&gt;    PBYTEArray frameBuffer;&lt;br /&gt;    PINDEX frameLen, frameOffs;&lt;br /&gt;};&lt;br /&gt;//这个是之读的文件是个g723编码的文件, 暂时不研究这个类相关的一切&lt;br /&gt;class G7231_OGMChannel : public PCM_OGMChannel&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(G7231_OGMChannel, PCM_OGMChannel);&lt;br /&gt;  public:&lt;br /&gt;    G7231_OGMChannel(MyH323Connection &amp; conn);&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    BOOL ReadFrame(PINDEX amount);&lt;br /&gt;    void CreateSilenceFrame(PINDEX amount);&lt;br /&gt;    void Synchronise(PINDEX amount);&lt;br /&gt;    BOOL IsWAVFileValid(PWAVFile *chan);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//连接,都是从这个类实例出来的&lt;br /&gt;class MyH323Connection : public H323Connection&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(MyH323Connection, H323Connection);&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    MyH323Connection(MyH323EndPoint &amp;, unsigned);&lt;br /&gt;    ~MyH323Connection();&lt;br /&gt;&lt;br /&gt;    // overrides from H323Connection&lt;br /&gt;    BOOL OpenAudioChannel(BOOL, unsigned, H323AudioCodec &amp; codec);&lt;br /&gt;    AnswerCallResponse OnAnswerCall(const PString &amp;, const H323SignalPDU &amp;amp;, H323SignalPDU &amp;);&lt;br /&gt;    BOOL OnStartLogicalChannel(H323Channel &amp; channel);&lt;br /&gt;    void OnUserInputString(const PString &amp; value);&lt;br /&gt;&lt;br /&gt;    // new functions&lt;br /&gt;    void StartRecording();&lt;br /&gt;    void Hangup();&lt;br /&gt;&lt;br /&gt;    void SetE164Number(const PString &amp; _num)&lt;br /&gt;      { e164Number = _num; }&lt;br /&gt;&lt;br /&gt;    PString GetE164Number() const&lt;br /&gt;      { return e164Number; }&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    void OnUserInputChar(char ch);&lt;br /&gt;    BOOL StartMenu(int menuNumber);&lt;br /&gt;    BOOL ProcessMenuCmd(const PString &amp; cmdStr);&lt;br /&gt;&lt;br /&gt;    const MyH323EndPoint &amp; ep;&lt;br /&gt;    PString product;&lt;br /&gt;    PTime   callStartTime;&lt;br /&gt;    PTime   recordStartTime;&lt;br /&gt;    PString basename;&lt;br /&gt;    PFilePath recordFn;&lt;br /&gt;    PString transmitCodecName, receiveCodecName;&lt;br /&gt;    BOOL    recordTrigger;&lt;br /&gt;    PMutex  connMutex;&lt;br /&gt;&lt;br /&gt;    PCM_RecordFile * recordFile;&lt;br /&gt;    PCM_OGMChannel * ogmChannel;&lt;br /&gt;&lt;br /&gt;    PString digits, lastDigits;&lt;br /&gt;    int currentMenu;&lt;br /&gt;    PStringList menuNames;&lt;br /&gt;&lt;br /&gt;    PString securityToken, e164Number;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//是录音&lt;br /&gt;class PCM_RecordFile : public PIndirectChannel&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(PCM_RecordFile, PIndirectChannel)&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    PCM_RecordFile(MyH323Connection &amp; conn, const PFilePath &amp;amp; fn, unsigned callLimit);&lt;br /&gt;    ~PCM_RecordFile();&lt;br /&gt;&lt;br /&gt;    BOOL Write(const void * buf, PINDEX len);&lt;br /&gt;    BOOL Close();&lt;br /&gt;    void StartRecording();&lt;br /&gt;&lt;br /&gt;    virtual void DelayFrame(PINDEX len);&lt;br /&gt;    virtual BOOL WriteFrame(const void * buf, PINDEX len);&lt;br /&gt;&lt;br /&gt;    BOOL WasRecordStarted() const { return recordStarted; }&lt;br /&gt;&lt;br /&gt;  protected:&lt;br /&gt;    MyH323Connection &amp; conn;&lt;br /&gt;    PTime finishTime;&lt;br /&gt;    PFilePath fn;&lt;br /&gt;    unsigned callLimit;&lt;br /&gt;    BOOL recordStarted;&lt;br /&gt;    BOOL timeLimitExceeded;&lt;br /&gt;    BOOL closed;&lt;br /&gt;    BOOL isPCM;&lt;br /&gt;    BOOL dataWritten;&lt;br /&gt;    PAdaptiveDelay delay;&lt;br /&gt;    PMutex pcmrecordMutex;&lt;br /&gt;    PFile *fileclass; // will point to a PWAVFile or PFile class&lt;br /&gt;};&lt;br /&gt;//录的结果是个g723文件, 我们暂时不考虑这个类相关的一切&lt;br /&gt;class G7231_RecordFile : public PCM_RecordFile&lt;br /&gt;{&lt;br /&gt;  PCLASSINFO(G7231_RecordFile, PCM_RecordFile);&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;    G7231_RecordFile(MyH323Connection &amp; conn, const PFilePath &amp;amp; fn, unsigned callLimit);&lt;br /&gt;    void DelayFrame(PINDEX len);&lt;br /&gt;    BOOL WriteFrame(const void * buf, PINDEX len);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#endif  // _Voxilla_MAIN_H&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// End of File ///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;这是main.cxx&lt;br /&gt;#include &lt;ptlib.h&gt;&lt;br /&gt;#include &lt;ptlib&gt;&lt;br /&gt;&lt;br /&gt;#include "version.h"&lt;br /&gt;#include "lpc10codec.h"&lt;br /&gt;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;#include "speexcodec.h"&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;#include "mscodecs.h"&lt;br /&gt;#include "opalvxml.h"&lt;br /&gt;#include "main.h"&lt;br /&gt;&lt;br /&gt;PCREATE_PROCESS(OpenAm);&lt;br /&gt;&lt;br /&gt;#define new PNEW&lt;br /&gt;&lt;br /&gt;//default 录音时间&lt;br /&gt;#define DEFAULT_MSG_LIMIT 30&lt;br /&gt;#define DEFAULT_CALL_LOG "call_log.txt"&lt;br /&gt;&lt;br /&gt;#define G7231_SAMPLES_PER_BLOCK 240&lt;br /&gt;&lt;br /&gt;#define CHECK_PCM   1&lt;br /&gt;#define CHECK_G7231 2&lt;br /&gt;&lt;br /&gt;#define MENU_PREFIX  "UserMenu-"&lt;br /&gt;&lt;br /&gt;static PMutex logMutex;&lt;br /&gt;static PTextFile logFile;&lt;br /&gt;static PFilePath logFilename = DEFAULT_CALL_LOG;&lt;br /&gt;&lt;br /&gt;PString G7231Ext = ".g723";&lt;br /&gt;PString WAVExt          = ".wav";&lt;br /&gt;PString PCMExt          = ".sw";&lt;br /&gt;&lt;br /&gt;//关于log的一切先不用看&lt;br /&gt;static void LogMessage(const PString &amp; str)&lt;br /&gt;{&lt;br /&gt;  PTime now;&lt;br /&gt;  PString msg = now.AsString("hh:mm:ss dd/MM/yyyy") &amp; str;&lt;br /&gt;  logMutex.Wait();&lt;br /&gt;&lt;br /&gt;  if (!logFile.IsOpen()) {&lt;br /&gt;    logFile.Open(logFilename, PFile::ReadWrite);&lt;br /&gt;    logFile.SetPosition(0, PFile::End);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  logFile.WriteLine(msg);&lt;br /&gt;&lt;br /&gt;  logFile.Close();&lt;br /&gt;  &lt;br /&gt;  logMutex.Signal();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void LogCall(const PFilePath &amp; fn,&lt;br /&gt;                    const PString &amp;amp; from,&lt;br /&gt;                    const PString &amp; user,&lt;br /&gt;                    unsigned len,&lt;br /&gt;                    const PString &amp;amp; codec,&lt;br /&gt;                    const PString &amp; product)&lt;br /&gt;{&lt;br /&gt;  PString addr = from;&lt;br /&gt;LogMessage(addr &amp; "\"" + user + "\"" &amp;amp; PString(PString::Unsigned, len) &amp; codec &amp;amp; "\"" + product + "\"" &amp; "\"" + fn + "\"");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;OpenAm::OpenAm()&lt;br /&gt;  : PProcess("OpenH323 Project", "OpenAM",&lt;br /&gt;             MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;OpenAm::~OpenAm()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void OpenAm::Main()&lt;br /&gt;{&lt;br /&gt;  cout &lt;&lt; GetName()&lt;br /&gt;       &lt;&lt; " Version " &lt;&lt; GetVersion(TRUE)&lt;br /&gt;       &lt;&lt; " by " &lt;&lt; GetManufacturer()&lt;br /&gt;       &lt;&lt; " on " &lt;&lt; GetOSClass() &lt;&lt;   &lt;&lt; GetOSName()&lt;br /&gt;       &lt;&lt; " (" &lt;&lt; GetOSVersion() &lt;&lt; - &lt;&lt; GetOSHardware() &lt;&lt; ")\n\n";&lt;br /&gt;&lt;br /&gt;// 分析命令行了&lt;br /&gt;  PConfigArgs args(GetArguments());&lt;br /&gt;&lt;br /&gt;  args.Parse(&lt;br /&gt;             "D-disable:"&lt;br /&gt;             "d-directory:"&lt;br /&gt;             "g-gatekeeper:"         "n-no-gatekeeper."&lt;br /&gt;             "-g711-ulaw."           "-no-g711-ulaw."&lt;br /&gt;             "-g711-alaw."           "-no-g711-alaw."&lt;br /&gt;             "-g711message:"         "-no-g711message."&lt;br /&gt;             "-g7231."               "-no-g7231."&lt;br /&gt;             "-g7231message:"        "-no-g7231message."&lt;br /&gt;             "-gsm."                 "-no-gsm."&lt;br /&gt;             "-gsmmessage:"          "-no-gsmmessage."&lt;br /&gt;             "h-help."&lt;br /&gt;             "H-hangup."             "-no-hangup."&lt;br /&gt;             "i-interface:"          "-no-interface."&lt;br /&gt;             "k-kill."               "-no-kill."&lt;br /&gt;             "l-limit:"              "-no-limit."&lt;br /&gt;             "-listenport:"          "-no-listenport."&lt;br /&gt;             "-lpc10message:"        "-no-lpc10message."&lt;br /&gt;             "-speexmessage:"        "-no-speexmessage."&lt;br /&gt;             "m-message:"            "-no-message."&lt;br /&gt;             "-no-recordg7231."&lt;br /&gt;#if PTRACING&lt;br /&gt;             "o-output:"&lt;br /&gt;#endif&lt;br /&gt;             "P-prefer:"&lt;br /&gt;             "-pcm."                 "-no-pcm."&lt;br /&gt;             "-pcmmessage:"          "-no-pcmmessage."&lt;br /&gt;             "-port:"&lt;br /&gt;             "q-quicknet:"           "-no-quicknet:"&lt;br /&gt;             "r-run:"                "-no-run."&lt;br /&gt;      "-recordraw."&lt;br /&gt;             "-require-gatekeeper."  "-no-require-gatekeeper."&lt;br /&gt;             "-save."&lt;br /&gt;#if PMEMORY_CHECK&lt;br /&gt;             "-setallocationbreakpoint:"&lt;br /&gt;#endif&lt;br /&gt;#if PTRACING&lt;br /&gt;             "t-trace."&lt;br /&gt;#endif&lt;br /&gt;      "u-username:"           "-no-username."&lt;br /&gt;          , FALSE);&lt;br /&gt;&lt;br /&gt;#if PMEMORY_CHECK&lt;br /&gt;  if (args.HasOption("setallocationbreakpoint"))&lt;br /&gt;    PMemoryHeap::SetAllocationBreakpoint(args.GetOptionString("setallocationbreakpoint").AsInteger());&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;#if PTRACING&lt;br /&gt;  PTrace::Initialise(args.GetOptionCount( ),&lt;br /&gt;                     args.HasOption(o) ? (const char *)args.GetOptionString(o) : NULL);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;  if (args.HasOption(h)) {&lt;br /&gt;    cout &lt;&lt; "Usage : " &lt;&lt; GetName() &lt;&lt; " [options]\n"&lt;br /&gt;            "Options:\n"&lt;br /&gt;            "  -d --directory dir  : Put recorded mesages into dir\n"&lt;br /&gt;" -l --limit secs : Limit recorded messages to secs duration (default " &lt;&lt; DEFAULT_MSG_LIMIT &lt;&lt; ")\n"&lt;br /&gt;            "  -m --pcmmessage fn  : Set outgoing message for PCM derived codecs (G.711/GSM) to fn\n"&lt;br /&gt;            "  --g7231message fn   : Set outgoing message for G723.1 codec to fn\n"&lt;br /&gt;            "  --g711message fn    : Set outgoing message for G711 codec to fn\n"&lt;br /&gt;            "  --gsmmessage fn     : Set outgoing message for GSM codec to fn\n"&lt;br /&gt;            "  --lpc10message fn   : Set outgoing message for LPC10 codec to fn\n"&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;            "  --speexmessage fn   : Set outgoing message for Speex codec to fn\n"&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;            "  --recordraw         : Record PCM audo in raw files (.sw) instead of .wav\n"&lt;br /&gt;            "  -r --run cmd        : Run this command after each recorded message\n"&lt;br /&gt;            "  -k --kill           : Kill recorded files after user command\n"&lt;br /&gt;            "  -H --hangup         : hangup after playing message\n"&lt;br /&gt;            "  -u --username str   : Set the local endpoint name to str\n"&lt;br /&gt;            "  -i --interface ip   : Bind to a specific interface\n"&lt;br /&gt;            "  --listenport port   : Listen on a specific port\n"&lt;br /&gt;            "  -g --gatekeeper host: Specify gatekeeper host.\n"&lt;br /&gt;            "  -n --no-gatekeeper  : Disable gatekeeper discovery.\n"&lt;br /&gt;            "  --require-gatekeeper: Exit if gatekeeper discovery fails.\n"&lt;br /&gt;            "  -D --disable codec  : Disable the specified codec (may be used multiple times)\n"&lt;br /&gt;            "  -P --prefer codec   : Prefer the specified codec (may be used multiple times)\n"&lt;br /&gt;#if PTRACING&lt;br /&gt;            "  -t --trace          : Enable trace, use multiple times for more detail\n"&lt;br /&gt;            "  -o --output         : File for trace output, default is stderr\n"&lt;br /&gt;#endif&lt;br /&gt;            "     --save           : Save arguments in configuration file\n"&lt;br /&gt;            "  -h --help           : Display this help message\n";&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  args.Save("save");&lt;br /&gt;&lt;br /&gt;//是指有IXJ卡吗? 我想你肯定没有, 那是电话卡 不用管他&lt;br /&gt;#if HAS_IXJ&lt;br /&gt;  if (args.GetCount() &gt; 0) {&lt;br /&gt;    if (args[0] *= "record") &lt;br /&gt;      RecordFile(args);&lt;br /&gt;    else if (args[0] *= "play") &lt;br /&gt;      PlayFile(args);&lt;br /&gt;    else&lt;br /&gt;      cerr &lt;&lt; "unknown command \"" &lt;&lt; args[0] &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;  unsigned callLimit = DEFAULT_MSG_LIMIT;&lt;br /&gt;  if (args.HasOption(l)) {&lt;br /&gt;    callLimit = args.GetOptionString(l).AsInteger();&lt;br /&gt;    if (callLimit &gt; 3600) {&lt;br /&gt;cout &lt;&lt; "warning: maximum call length " &lt;&lt; callLimit &lt;&lt; " is out of range. Using " &lt;&lt; DEFAULT_MSG_LIMIT &lt;&lt; " instead\n";&lt;br /&gt;      callLimit = DEFAULT_MSG_LIMIT;&lt;br /&gt;    } else if (callLimit == 0)&lt;br /&gt;      cout &lt;&lt; "warning: recorded message call limit disabled\n";&lt;br /&gt;  }&lt;br /&gt;  cout &lt;&lt; "Recorded messages limited to " &lt;&lt; callLimit &lt;&lt; " seconds\n";&lt;br /&gt;&lt;br /&gt;  PString runCmd;&lt;br /&gt;  if (args.HasOption( )) {&lt;br /&gt;    runCmd = args.GetOptionString( );&lt;br /&gt;    cout &lt;&lt; "Executing \"" &lt;&lt; runCmd &lt;&lt; "\" after each message" &lt;&lt; endl;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  PDirectory dir;&lt;br /&gt;  if (args.HasOption(d))&lt;br /&gt;    dir = args.GetOptionString(d);&lt;br /&gt;&lt;br /&gt;  int flags = 0;&lt;br /&gt;&lt;br /&gt;  if (args.HasOption("no-recordg7231")) {&lt;br /&gt;    cout &lt;&lt; "Supressing recording of G723.1 messages" &lt;&lt; endl;&lt;br /&gt;    flags |= MyH323EndPoint::NoRecordG7231;&lt;br /&gt;  }&lt;br /&gt;  if (args.HasOption(k)) {&lt;br /&gt;    cout &lt;&lt; "Deleting recorded files after processing" &lt;&lt; endl;&lt;br /&gt;    if (runCmd.IsEmpty()) &lt;br /&gt;      cout &lt;&lt; "WARNING: recorded files will be deleted even though no run command is present" &lt;&lt; endl;&lt;br /&gt;    flags |= MyH323EndPoint::DeleteAfterRecord;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (args.HasOption(H))&lt;br /&gt;    flags |= MyH323EndPoint::HangupAfterPlay;&lt;br /&gt;  &lt;br /&gt;//创建H323 EndPoint&lt;br /&gt;  MyH323EndPoint endpoint(callLimit, runCmd, dir, flags);&lt;br /&gt;&lt;br /&gt;  PString userName = "OpenH323 Answering Machine v" + GetVersion();&lt;br /&gt;  if (args.HasOption(u))&lt;br /&gt;    userName = args.GetOptionString(u);&lt;br /&gt;  endpoint.SetLocalUserName(userName);&lt;br /&gt;&lt;br /&gt;  if (!endpoint.Initialise(args))&lt;br /&gt;    return;&lt;br /&gt;&lt;br /&gt;  // start the H.323 listener&lt;br /&gt;// 开始监听 H323有个默认的端口应该是1572 之类的 DefaultSignalPort, 我忘了&lt;br /&gt;  H323ListenerTCP * listener;&lt;br /&gt;  PIPSocket::Address interfaceAddress(INADDR_ANY);&lt;br /&gt;  WORD listenPort = H323ListenerTCP::DefaultSignalPort;&lt;br /&gt;&lt;br /&gt;  if (args.HasOption("listenport"))&lt;br /&gt;    listenPort = (WORD)args.GetOptionString("listenport").AsInteger();&lt;br /&gt;&lt;br /&gt;  if (args.HasOption(i))&lt;br /&gt;    interfaceAddress = PIPSocket::Address(args.GetOptionString(i));&lt;br /&gt;&lt;br /&gt;  listener  = new H323ListenerTCP(endpoint, interfaceAddress, listenPort);&lt;br /&gt;&lt;br /&gt;  if (!endpoint.StartListener(listener)) {&lt;br /&gt;    cout &lt;&lt;  "Could not open H.323 listener port on "&lt;br /&gt;         &lt;&lt;&gt;GetListenerPort() &lt;&lt; endl;&lt;br /&gt;    delete listener;&lt;br /&gt;    return;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;//gatekeeper 相关的东西我们也不必考虑 用-n这个参数这个端点就不会&lt;br /&gt;//去找gatekeeper&lt;br /&gt;&lt;br /&gt;  if (args.HasOption(g)) {&lt;br /&gt;    PString gkName = args.GetOptionString(g);&lt;br /&gt;    if (endpoint.SetGatekeeper(gkName, new H323TransportUDP(endpoint)))&lt;br /&gt;      cout &lt;&lt; "Gatekeeper set: " &lt;&lt; *endpoint.GetGatekeeper() &lt;&lt; endl;&lt;br /&gt;    else {&lt;br /&gt;      cout &lt;&lt; "Error registering with gatekeeper at \"" &lt;&lt; gkName &lt;&lt; \" &lt;&lt; endl;&lt;br /&gt;      return;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  else if (!args.HasOption( )) {&lt;br /&gt;    cout &lt;&lt; "Searching for gatekeeper..." &lt;&lt; flush;&lt;br /&gt;    if (endpoint.DiscoverGatekeeper(new H323TransportUDP(endpoint)))&lt;br /&gt;      cout &lt;&lt; "\nGatekeeper found: " &lt;&lt; *endpoint.GetGatekeeper() &lt;&lt; endl;&lt;br /&gt;    else {&lt;br /&gt;      cout &lt;&lt; "\nNo gatekeeper found." &lt;&lt; endl;&lt;br /&gt;      if (args.HasOption("require-gatekeeper"))&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Waiting for incoming calls for \"" &lt;&lt; endpoint.GetLocalUserName() &lt;&lt; \" &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;//瞧瞧, 这就是主进程干的这点事, Sleep的是毫秒&lt;br /&gt;  for (;;) &lt;br /&gt;    PThread::Current()-&gt;Sleep(5000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;MyH323EndPoint::MyH323EndPoint(unsigned _callLimit,&lt;br /&gt;                               const PString &amp; _runCmd,&lt;br /&gt;                               const PDirectory &amp;amp; _dir,&lt;br /&gt;                               int   _flags)&lt;br /&gt;  : callLimit(_callLimit), runCmd(_runCmd), dir(_dir), flags(_flags)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL MyH323EndPoint::OnIncomingCall(H323Connection &amp; _conn,&lt;br /&gt;                                    const H323SignalPDU &amp;amp; setupPDU,&lt;br /&gt;                                    H323SignalPDU &amp;)&lt;br /&gt;{&lt;br /&gt; //传过来的是引用, 引用这个东西必须马上赋值&lt;br /&gt;  MyH323Connection &amp;amp; conn = (MyH323Connection &amp;)_conn;&lt;br /&gt;&lt;br /&gt;  // see if incoming call is to a getway address&lt;br /&gt;  PString number;&lt;br /&gt;  if (setupPDU.GetDestinationE164(number)) &lt;br /&gt;    conn.SetE164Number(number);&lt;br /&gt;&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;//这个没什么异常, 都这样做&lt;br /&gt;H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference)&lt;br /&gt;{&lt;br /&gt;  return new MyH323Connection(*this, callReference);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//分析命令, 看看应该使用什么样的能力去交换, &lt;br /&gt;// 我们在使用的时候指定—g711message&lt;br /&gt;//就是说只是用g711 的alaw或者mulaw&lt;br /&gt;//很多废话就不用看了&lt;br /&gt;//除了和g711相关的其他都没有用处了&lt;br /&gt;&lt;br /&gt;BOOL MyH323EndPoint::Initialise(PConfigArgs &amp; args)&lt;br /&gt;{&lt;br /&gt;  // format for record files, raw or wav&lt;br /&gt;  if (args.HasOption("recordraw")) &lt;br /&gt;    SetRecordWav(FALSE);&lt;br /&gt;  else&lt;br /&gt;    SetRecordWav(TRUE);&lt;br /&gt;&lt;br /&gt;  // get G723.1 OGM&lt;br /&gt;  if (args.HasOption("g7231message"))&lt;br /&gt;    g7231Ogm = args.GetOptionString("g7231message");&lt;br /&gt;  else if (args.HasOption(m))  {&lt;br /&gt;    if (PFile::Exists(args.GetOptionString(m) + "_g7231" + WAVExt)) {&lt;br /&gt;      g7231Ogm = args.GetOptionString(m) + "_g7231" + WAVExt;&lt;br /&gt;    }&lt;br /&gt;    else if (PFile::Exists(args.GetOptionString(m) + PCMExt)) {&lt;br /&gt;      g7231Ogm = args.GetOptionString(m) + G7231Ext;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!g7231Ogm.IsEmpty()) {&lt;br /&gt;    if ((g7231Ogm.Find("%s") == P_MAX_INDEX) &amp;&amp;amp; !PFile::Exists(g7231Ogm)) {&lt;br /&gt;      cout &lt;&lt; "warning: cannot open G723.1 OGM file \"" &lt;&lt; g7231Ogm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      g7231Ogm = "";&lt;br /&gt;    } &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (g7231Ogm.IsEmpty()) &lt;br /&gt;    cout &lt;&lt; "No G.723.1 outgoing message set\n";&lt;br /&gt;  else {&lt;br /&gt;    cout &lt;&lt; "Using \"" &lt;&lt; g7231Ogm &lt;&lt; "\" as G.723.1 outgoing message\n";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  // Get the OGM message for the PCM codecs&lt;br /&gt;  // Check if the file specified exists. If it does, use it.&lt;br /&gt;  // If it does not exist, try with .wav and .sw extensions.&lt;br /&gt;  if (args.HasOption("pcmmessage")) {&lt;br /&gt;    pcmOgm = args.GetOptionString("pcmmessage");&lt;br /&gt;  }&lt;br /&gt;  else if (args.HasOption(m)) {&lt;br /&gt;    if (g7231Ogm.Find("%s") == P_MAX_INDEX) {&lt;br /&gt;      pcmOgm = args.GetOptionString(m);&lt;br /&gt;    } else {&lt;br /&gt;      if (PFile::Exists(args.GetOptionString(m))) {&lt;br /&gt;        pcmOgm = args.GetOptionString(m);&lt;br /&gt;      }&lt;br /&gt;      else if (PFile::Exists(args.GetOptionString(m) + WAVExt)) {&lt;br /&gt;        pcmOgm = args.GetOptionString(m) + WAVExt;&lt;br /&gt;      }&lt;br /&gt;      else if (PFile::Exists(args.GetOptionString(m) + PCMExt)) {&lt;br /&gt;        pcmOgm = args.GetOptionString(m) + PCMExt;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  // By default, use the pcmOgm for all the PCM codecs, but allow the user&lt;br /&gt;  // to override them.&lt;br /&gt;  gsmOgm   = pcmOgm;&lt;br /&gt;  g711Ogm  = pcmOgm;&lt;br /&gt;  lpc10Ogm = pcmOgm;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;  speexOgm = pcmOgm;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  // We can set the filename for specific codecs.&lt;br /&gt;  if (args.HasOption("gsmmessage")) &lt;br /&gt;gsmOgm = args.GetOptionString("gsmmessage");&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//这句话用的着&lt;br /&gt;  if (args.HasOption("g711message")) &lt;br /&gt;    g711Ogm = args.GetOptionString("g711message");&lt;br /&gt;&lt;br /&gt;  if (args.HasOption("lpc10message")) &lt;br /&gt;    lpc10Ogm = args.GetOptionString("lpc10message");&lt;br /&gt;//这是一个codec设备, 你没有!&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;  if (args.HasOption("speexmessage")) &lt;br /&gt;    speexOgm = args.GetOptionString("speexmessage");&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;  // Check GSM OGM message&lt;br /&gt;  if (!gsmOgm.IsEmpty()) {&lt;br /&gt;    if ((g7231Ogm.Find("%s") == P_MAX_INDEX) &amp;&amp;amp; !PFile::Exists(gsmOgm)) {&lt;br /&gt;      cout &lt;&lt; "warning: cannot open GSM OGM file \"" &lt;&lt; gsmOgm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      gsmOgm = "";&lt;br /&gt;    }&lt;br /&gt;  } &lt;br /&gt;  if (gsmOgm.IsEmpty()) &lt;br /&gt;    cout &lt;&lt; "No GSM outgoing message set\n";&lt;br /&gt;  else {&lt;br /&gt;    cout &lt;&lt; "Using \"" &lt;&lt; gsmOgm &lt;&lt; "\" as GSM outgoing message\n";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Check G.711 OGM message &lt;br /&gt;  if (!g711Ogm.IsEmpty()) {&lt;br /&gt;    if ((g7231Ogm.Find("%s") == P_MAX_INDEX) &amp;&amp;amp; !PFile::Exists(g711Ogm)) {&lt;br /&gt;      cout &lt;&lt; "warning: cannot open G711 OGM file \"" &lt;&lt; g711Ogm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      g711Ogm = "";&lt;br /&gt;    }&lt;br /&gt;  } &lt;br /&gt;  if (g711Ogm.IsEmpty()) &lt;br /&gt;    cout &lt;&lt; "No G711 outgoing message set\n";&lt;br /&gt;  else {&lt;br /&gt;    cout &lt;&lt; "Using \"" &lt;&lt; g711Ogm &lt;&lt; "\" as G.711 outgoing message\n";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Check LPC10 OGM message &lt;br /&gt;  if (!lpc10Ogm.IsEmpty()) {&lt;br /&gt;    if ((g7231Ogm.Find("%s") == P_MAX_INDEX) &amp;&amp;amp; !PFile::Exists(lpc10Ogm)) {&lt;br /&gt;      cout &lt;&lt; "warning: cannot open LPC10 OGM file \"" &lt;&lt; lpc10Ogm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      lpc10Ogm = "";&lt;br /&gt;    }&lt;br /&gt;  } &lt;br /&gt;  if (lpc10Ogm.IsEmpty()) &lt;br /&gt;    cout &lt;&lt; "No LPC10 outgoing message set\n";&lt;br /&gt;  else {&lt;br /&gt;    cout &lt;&lt; "Using \"" &lt;&lt; lpc10Ogm &lt;&lt; "\" as LPC10 outgoing message\n";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;  // Check Speex OGM message &lt;br /&gt;  if (!speexOgm.IsEmpty()) {&lt;br /&gt;    if ((g7231Ogm.Find("%s") == P_MAX_INDEX) &amp;&amp;amp; !PFile::Exists(speexOgm)) {&lt;br /&gt;      cout &lt;&lt; "warning: cannot open Speex OGM file \"" &lt;&lt; speexOgm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      speexOgm = "";&lt;br /&gt;    }&lt;br /&gt;  } &lt;br /&gt;  if (speexOgm.IsEmpty()) &lt;br /&gt;    cout &lt;&lt; "No Speex outgoing message set\n";&lt;br /&gt;  else {&lt;br /&gt;    cout &lt;&lt; "Using \"" &lt;&lt; speexOgm &lt;&lt; "\" as Speex outgoing message\n";&lt;br /&gt;  }&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  if (g7231Ogm.IsEmpty() &amp;&amp;amp; gsmOgm.IsEmpty() &amp;&amp;amp; g711Ogm.IsEmpty()&lt;br /&gt;                         &amp;&amp;amp; lpc10Ogm.IsEmpty() &lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;    &amp;&amp;amp; speexOgm.IsEmpty()&lt;br /&gt;#endif&lt;br /&gt;    ) {&lt;br /&gt;    cerr &lt;&lt; "Must specify at least one outgoing message" &lt;&lt; endl;&lt;br /&gt;    return FALSE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!g7231Ogm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new G7231_File_Capability);&lt;br /&gt;&lt;br /&gt;  if (!gsmOgm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new H323_GSM0610Capability);&lt;br /&gt;&lt;br /&gt;  if (!gsmOgm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new MicrosoftGSMAudioCapability);&lt;br /&gt;&lt;br /&gt;//这是 AM Endpoint的能力 支持g711的alaw和ulaw&lt;br /&gt;  if (!g711Ogm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new H323_G711Capability(H323_G711Capability::muLaw, H323_G711Capability::At64k));&lt;br /&gt;&lt;br /&gt;  if (!g711Ogm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new H323_G711Capability(H323_G711Capability::ALaw, H323_G711Capability::At64k));&lt;br /&gt;&lt;br /&gt;//没有用了&lt;br /&gt;  if (!lpc10Ogm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new H323_LPC10Capability(*this));&lt;br /&gt;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;  if (!speexOgm.IsEmpty())&lt;br /&gt;    SetCapability(0, 0, new SpeexNarrow3AudioCapability());&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;  capabilities.Remove(args.GetOptionString(D).Lines());&lt;br /&gt;  capabilities.Reorder(args.GetOptionString(P).Lines());&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Codecs (in preference order):\n" &lt;&lt; setprecision(2) &lt;&lt; capabilities &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;//录音通道, 解码对象所附着的通道&lt;br /&gt;//写文件&lt;br /&gt;PCM_RecordFile::PCM_RecordFile(MyH323Connection &amp; _conn, const PFilePath &amp;amp; _fn, unsigned _callLimit)&lt;br /&gt;  : conn(_conn), fn(_fn), callLimit(_callLimit)&lt;br /&gt;{&lt;br /&gt;  recordStarted = FALSE;&lt;br /&gt;  timeLimitExceeded = FALSE;&lt;br /&gt;  closed        = FALSE;&lt;br /&gt;  dataWritten   = FALSE;&lt;br /&gt;&lt;br /&gt;  // If the file name ends in .wav then open the output as a WAV file.&lt;br /&gt;  // Otherwise open it as a raw file.&lt;br /&gt;  if ((_fn.Right(4)).ToLower() == ".wav")&lt;br /&gt;    fileclass = new PWAVFile(_fn, PFile::WriteOnly,&lt;br /&gt;        PFile::ModeDefault,PWAVFile::PCM_WavFile);&lt;br /&gt;  else&lt;br /&gt;    fileclass = new PFile(_fn, PFile::WriteOnly);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PCM_RecordFile::StartRecording()&lt;br /&gt;{&lt;br /&gt;  PWaitAndSignal mutex(pcmrecordMutex);&lt;br /&gt;&lt;br /&gt;  if (recordStarted)&lt;br /&gt;    return;&lt;br /&gt;&lt;br /&gt;  PTRACE(1, "Starting recording to " &lt;&lt; fn);&lt;br /&gt;&lt;br /&gt;  PTime now;&lt;br /&gt;  recordStarted = TRUE;&lt;br /&gt;  finishTime = now + (callLimit * 1000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL PCM_RecordFile::Close()&lt;br /&gt;{&lt;br /&gt;  PWaitAndSignal mutex(pcmrecordMutex);&lt;br /&gt;&lt;br /&gt;  closed = TRUE;&lt;br /&gt;  return fileclass-&gt;Close();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL PCM_RecordFile::Write(const void * buf, PINDEX len)&lt;br /&gt;{&lt;br /&gt;  // Wait for the mutex, and Signal it at the end of this function&lt;br /&gt;  PWaitAndSignal mutex(pcmrecordMutex);&lt;br /&gt;&lt;br /&gt;  // If the record file has been closed, or if the time limit has&lt;br /&gt;  // been exceeded, then return immediatly.&lt;br /&gt;  if (closed || timeLimitExceeded)&lt;br /&gt;    return FALSE;&lt;br /&gt;&lt;br /&gt;  if (!recordStarted) {&lt;br /&gt;    DelayFrame(len);&lt;br /&gt;    return TRUE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  PTime now;&lt;br /&gt;  if ((callLimit != 0) &amp;&amp;amp; (now &gt;= finishTime)) {&lt;br /&gt;    PTRACE(1, "Terminating call due to timeout");&lt;br /&gt;    conn.ClearCall();&lt;br /&gt;    timeLimitExceeded = TRUE;&lt;br /&gt;    return TRUE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  DelayFrame(len);&lt;br /&gt;&lt;br /&gt;  dataWritten = TRUE;&lt;br /&gt;&lt;br /&gt;  return WriteFrame(buf, len);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL PCM_RecordFile::WriteFrame(const void * buf, PINDEX len)&lt;br /&gt;{&lt;br /&gt;  //cerr &lt;&lt; "Writing PCM " &lt;&lt; len &lt;&lt; endl;&lt;br /&gt;  return  fileclass-&gt;Write(buf, len);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PCM_RecordFile::DelayFrame(PINDEX len)&lt;br /&gt;{&lt;br /&gt;  delay.Delay(len/16);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PCM_RecordFile::~PCM_RecordFile()&lt;br /&gt;{&lt;br /&gt;  PWaitAndSignal mutex(pcmrecordMutex);&lt;br /&gt;&lt;br /&gt;  if (!dataWritten) {&lt;br /&gt;    PTRACE(1, "Deleting " &lt;&lt; fn &lt;&lt; " as no data recorded");&lt;br /&gt;    fileclass-&gt;Remove(fn);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  delete fileclass;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;// Override some of the PCM_RecordFile functions to write&lt;br /&gt;// G723.1 data instead of PCM data.&lt;br /&gt;&lt;br /&gt;G7231_RecordFile::G7231_RecordFile(MyH323Connection &amp; _conn, const PFilePath &amp;amp; _fn, unsigned _callLimit)&lt;br /&gt;  : PCM_RecordFile(_conn, _fn, _callLimit)&lt;br /&gt;{&lt;br /&gt;  // If the record file is a .wav file, we need to close the file&lt;br /&gt;  // that PCM_RecordFile will have opened, and reopen it as a G.723.1 Wav file.&lt;br /&gt;  if ((_fn.Right(4)).ToLower() == ".wav") {&lt;br /&gt;    fileclass-&gt;Remove(_fn);&lt;br /&gt;    delete fileclass;&lt;br /&gt;    fileclass = new PWAVFile(_fn, PFile::WriteOnly,&lt;br /&gt;        PFile::ModeDefault,PWAVFile::G7231_WavFile);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL G7231_RecordFile::WriteFrame(const void * buf, PINDEX /*len*/)&lt;br /&gt;{&lt;br /&gt;  int frameLen = G7231_File_Codec::GetFrameLen(*(BYTE *)buf);&lt;br /&gt;//  cerr &lt;&lt; "Writing G7231 " &lt;&lt; frameLen &lt;&lt; endl;&lt;br /&gt;  return fileclass-&gt;Write(buf, frameLen);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void G7231_RecordFile::DelayFrame(PINDEX /*len*/)&lt;br /&gt;{&lt;br /&gt;  // Ignore the len parameter as that is the compressed size.&lt;br /&gt;  // We must delay by the actual sample time.&lt;br /&gt;  delay.Delay((G7231_SAMPLES_PER_BLOCK*2)/16);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;///////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;static BOOL MatchString(const PString &amp; str1, const PString str2)&lt;br /&gt;{&lt;br /&gt;  if (str1.GetLength() != str2.GetLength())&lt;br /&gt;    return FALSE;&lt;br /&gt;&lt;br /&gt;  PINDEX len = str1.GetLength();&lt;br /&gt;&lt;br /&gt;  PINDEX i;&lt;br /&gt;  for (i = 0; i &lt; len; i++) &lt;br /&gt;    if ((str1[i] != ?) &amp;&amp;amp; (str2[i] != ?) &amp;&amp;amp; (str1[i] != str2[i]))&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static PINDEX FindMatch(const PStringList &amp; list, const PString &amp;amp; key)&lt;br /&gt;{&lt;br /&gt;  PINDEX maxKeyLen = 0;&lt;br /&gt;  PINDEX i;&lt;br /&gt;&lt;br /&gt;  PINDEX keyLen = key.GetLength();&lt;br /&gt;  PINDEX listLen = list.GetSize();&lt;br /&gt;&lt;br /&gt;  for (i = 0; i &lt; listLen; i++)&lt;br /&gt;    maxKeyLen = PMAX(maxKeyLen, list[i].GetLength());&lt;br /&gt;&lt;br /&gt;  if (keyLen == 0 || maxKeyLen == 0)&lt;br /&gt;    return P_MAX_INDEX;&lt;br /&gt;&lt;br /&gt;  if (keyLen &gt; maxKeyLen)&lt;br /&gt;    return P_MAX_INDEX;&lt;br /&gt;&lt;br /&gt;  PINDEX len = 1;&lt;br /&gt;  while (len &lt;= keyLen) {&lt;br /&gt;    PString subStr = key.Left(len);&lt;br /&gt;&lt;br /&gt;    PINDEX matches = 0;&lt;br /&gt;    PINDEX lastMatch = P_MAX_INDEX;&lt;br /&gt;    PINDEX i;&lt;br /&gt;&lt;br /&gt;    // look for a match to the substring&lt;br /&gt;    for (i = 0; i &lt; list.GetSize(); i++) {&lt;br /&gt;      if ((list[i].GetLength() &gt;= keyLen) &amp;&amp;amp; MatchString(list[i].Left(len), subStr)) {&lt;br /&gt;        matches++;&lt;br /&gt;        lastMatch = i;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // if we got ONE match, we have a winner&lt;br /&gt;    if (matches == 1)&lt;br /&gt;      return lastMatch+1;&lt;br /&gt;&lt;br /&gt;    // if we have no matches, then there is no point continuing&lt;br /&gt;    if (matches == 0)&lt;br /&gt;      return P_MAX_INDEX;&lt;br /&gt;&lt;br /&gt;    // if we have more than one match, try the next char&lt;br /&gt;    len++;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // too many matches&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;MyH323Connection::MyH323Connection(MyH323EndPoint &amp; _ep, unsigned callReference)&lt;br /&gt;  : H323Connection(_ep, callReference), ep(_ep)&lt;br /&gt;{&lt;br /&gt;  basename = psprintf("%04i%02i%02i_%02i%02i%02i", callStartTime.GetYear(), callStartTime.GetMonth(),  callStartTime.GetDay(),&lt;br /&gt;callStartTime.GetHour(), callStartTime.GetMinute(), callStartTime.GetSecond());&lt;br /&gt;  recordFile = NULL;&lt;br /&gt;  ogmChannel = NULL;&lt;br /&gt;&lt;br /&gt;  receiveCodecName = transmitCodecName = "none";&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Opening connection" &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  currentMenu = 0;&lt;br /&gt;  digits = "";&lt;br /&gt;&lt;br /&gt;  PConfig config;&lt;br /&gt;  PStringList sections = config.GetSections();&lt;br /&gt;  PINDEX i;&lt;br /&gt;  for (i = 0; i &lt; sections.GetSize(); i++) {&lt;br /&gt;    if (sections[i].Find(MENU_PREFIX) == 0) &lt;br /&gt;      menuNames.AppendString(sections[i]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;MyH323Connection::~MyH323Connection()&lt;br /&gt;{&lt;br /&gt;  cout &lt;&lt; "Closing connection" &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  PTime now;&lt;br /&gt;  PTimeInterval interval = now - recordStartTime;&lt;br /&gt;  PString addr = GetControlChannel().GetRemoteAddress();&lt;br /&gt;&lt;br /&gt;  PString codecStr = receiveCodecName + "/" + transmitCodecName;&lt;br /&gt;  unsigned duration = (unsigned)((interval.GetMilliSeconds()+999)/1000);&lt;br /&gt;&lt;br /&gt;  LogCall(recordFn, addr, GetRemotePartyName(), duration, codecStr, product);&lt;br /&gt;&lt;br /&gt;  if ((recordFile!= NULL) &amp;&amp;amp; (recordFile-&gt;WasRecordStarted()) &amp;&amp;amp; !ep.GetRunCmd().IsEmpty()) {&lt;br /&gt;    PString cmdStr = ep.GetRunCmd() &amp;&lt;br /&gt;                     recordFn &amp;amp;&lt;br /&gt;                     "\" + addr + "\" &amp;&lt;br /&gt;                     "\"" + GetRemotePartyName() + "\"" &amp;amp;&lt;br /&gt;                     PString(PString::Unsigned, duration) &amp;&lt;br /&gt;                     "\"" + codecStr + "\"" &amp;amp;&lt;br /&gt;                     "\"" + product + "\"";&lt;br /&gt;    PTRACE(1, "Executing : " &lt;&lt; cmdStr);&lt;br /&gt;    system((const char *)cmdStr);&lt;br /&gt;  } else {&lt;br /&gt;    PTRACE(1, "No action to perform at end of record");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (ogmChannel != NULL)&lt;br /&gt;    delete ogmChannel;&lt;br /&gt;&lt;br /&gt;  if (recordFile != NULL)&lt;br /&gt;    delete recordFile;&lt;br /&gt;&lt;br /&gt;  if (ep.GetDeleteAfterRecord()) {&lt;br /&gt;    PTRACE(1, "Removing " &lt;&lt; recordFn &lt;&lt; " as requested by option");&lt;br /&gt;    PFile::Remove(recordFn);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;H323Connection::AnswerCallResponse&lt;br /&gt;     MyH323Connection::OnAnswerCall(const PString &amp; caller,&lt;br /&gt;                                    const H323SignalPDU &amp;amp; setupPDU,&lt;br /&gt;                                    H323SignalPDU &amp; /*connectPDU*/)&lt;br /&gt;{&lt;br /&gt;  product = "Unknown";&lt;br /&gt;&lt;br /&gt;  const H225_Setup_UUIE &amp; setup = setupPDU.m_h323_uu_pdu.m_h323_message_body;&lt;br /&gt;  const H225_EndpointType &amp; epInfo = setup.m_sourceInfo;&lt;br /&gt;&lt;br /&gt;  if (epInfo.HasOptionalField(H225_EndpointType::e_vendor)) {&lt;br /&gt;    const H225_VendorIdentifier &amp; vendorInfo = epInfo.m_vendor;&lt;br /&gt;    if (vendorInfo.HasOptionalField(H225_VendorIdentifier::e_productId))&lt;br /&gt;      product = vendorInfo.m_productId.AsString();&lt;br /&gt;    if (vendorInfo.HasOptionalField(H225_VendorIdentifier::e_versionId))&lt;br /&gt;      product = product + "/" + vendorInfo.m_versionId.AsString();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  cout &lt;&lt; "Accepting call from " &lt;&lt; caller &lt;&lt; " using " &lt;&lt; product &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;  return AnswerCallNow;&lt;br /&gt;}&lt;br /&gt;//&lt;br /&gt;//关键的东西都在这里&lt;br /&gt;// 从传入的codec的的类别来判断H323 Endpoint正在使用什么样的codec进行数据的编码解码&lt;br /&gt;//显然我们一开始的设定影响了现在的codec, 我们设定H323 Endpoint 的能力是G711,&lt;br /&gt;// 所以这里应该是IsDescendant from H323_muLawCodec::Class() 或者H323_ALawCodec::Class().&lt;br /&gt;//&lt;br /&gt;BOOL MyH323Connection::OpenAudioChannel(BOOL isEncoding, &lt;br /&gt;                                        unsigned /* bufferSize */, &lt;br /&gt;                                        H323AudioCodec &amp; codec)&lt;br /&gt;{&lt;br /&gt;  codec.SetSilenceDetectionMode(H323AudioCodec::NoSilenceDetection);&lt;br /&gt;  PStringStream codecName;&lt;br /&gt;  codecName &lt;&lt; codec;&lt;br /&gt;&lt;br /&gt;  PString ogm;&lt;br /&gt;  BOOL isPCM = FALSE;&lt;br /&gt;&lt;br /&gt;  if (codec.IsDescendant(G7231_File_Codec::Class())) {&lt;br /&gt;    ogm   = ep.GetG7231OGM();&lt;br /&gt;    isPCM = FALSE;&lt;br /&gt;  } else if (codec.IsDescendant(H323_GSM0610Codec::Class())) {&lt;br /&gt;    ogm   = ep.GetGSMOGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;  } else if (codec.IsDescendant(MicrosoftGSMCodec::Class())) {&lt;br /&gt;    ogm   = ep.GetGSMOGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;  } else if (codec.IsDescendant(H323_muLawCodec::Class())) {&lt;br /&gt;    ogm   = ep.GetG711OGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;  } else if (codec.IsDescendant(H323_ALawCodec::Class())) {&lt;br /&gt;    ogm   = ep.GetG711OGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;  } else if (codec.IsDescendant(H323_LPC10Codec::Class())) {&lt;br /&gt;    ogm   = ep.GetLPC10OGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;#ifdef SPEEX_CODEC&lt;br /&gt;  } else if (codec.IsDescendant(SpeexCodec::Class())) {&lt;br /&gt;    ogm   = ep.GetSPEEXOGM();&lt;br /&gt;    isPCM = TRUE;&lt;br /&gt;#endif&lt;br /&gt;  } else {&lt;br /&gt;    cerr &lt;&lt; "Unknown codec \"" &lt;&lt; codecName &lt;&lt; endl;&lt;br /&gt;    return FALSE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  PWaitAndSignal mutex(connMutex);&lt;br /&gt;&lt;br /&gt;  if ((recordFile == NULL) &amp;&amp;amp; (isEncoding == FALSE)) {&lt;br /&gt;    if (isPCM) {&lt;br /&gt;      if (ep.GetRecordWav() == TRUE)&lt;br /&gt;       recordFn = ep.GetDirectory() + (basename + ".wav");&lt;br /&gt;      else&lt;br /&gt;       recordFn = ep.GetDirectory() + (basename + ".sw");&lt;br /&gt;      recordFile = new PCM_RecordFile  (*this, recordFn, ep.GetCallLimit());&lt;br /&gt;    } else {&lt;br /&gt;      if (ep.GetRecordWav() == TRUE)&lt;br /&gt;       recordFn = ep.GetDirectory() + (basename + ".wav");&lt;br /&gt;      else&lt;br /&gt;       recordFn = ep.GetDirectory() + (basename + ".g723");&lt;br /&gt;      recordFile = new G7231_RecordFile(*this, recordFn, ep.GetCallLimit());&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;// 这里创建了我们想用的通道&lt;br /&gt;  if ((ogmChannel == NULL) &amp;&amp;amp; (isEncoding == TRUE)) {&lt;br /&gt;    if (isPCM)&lt;br /&gt;      ogmChannel = new PCM_OGMChannel(*this);&lt;br /&gt;    else&lt;br /&gt;      ogmChannel = new G7231_OGMChannel(*this);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (isEncoding) {&lt;br /&gt;&lt;br /&gt;    if (ep.GetHangupAfterPlay())&lt;br /&gt;      ogmChannel-&gt;SetPlayOnce();&lt;br /&gt;&lt;br /&gt;    if (ogm.Find("%s"))&lt;br /&gt;      ogm.Replace("%s", e164Number);&lt;br /&gt;&lt;br /&gt;    transmitCodecName = codecName;&lt;br /&gt;    if (!StartMenu(0)) {&lt;br /&gt;      if (!PFile::Exists(ogm))&lt;br /&gt;        cerr &lt;&lt; "error: cannot find OGM \"" &lt;&lt; ogm &lt;&lt; "\"" &lt;&lt; endl;&lt;br /&gt;      else&lt;br /&gt;        ogmChannel-&gt;QueueFile(ogm);&lt;br /&gt;      if (!ep.GetNoRecordG7231())&lt;br /&gt;        ogmChannel-&gt;SetRecordTrigger();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//这里讲通道附着在codec上, 放音&lt;br /&gt;    codec.AttachChannel(ogmChannel, FALSE);&lt;br /&gt;  } else {&lt;br /&gt;receiveCodecName = codecName;&lt;br /&gt;//这里讲通道附着在codec上. 录音&lt;br /&gt;    codec.AttachChannel(recordFile, FALSE);&lt;br /&gt;  }&lt;br /&gt;  return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;BOOL MyH323Connection::OnStartLogicalChannel(H323Channel &amp; channel)&lt;br /&gt;{&lt;br /&gt;  if (!H323Connection::OnStartLogicalChannel(channel))&lt;br /&gt;    return FALSE;&lt;br /&gt;&lt;br /&gt;  cout &lt;&lt; "Started logical channel: ";&lt;br /&gt;&lt;br /&gt;  switch (channel.GetDirection()) {&lt;br /&gt;    case H323Channel::IsT&lt;/ptlib&gt;&lt;/ptlib.h&gt;&lt;/ptclib&gt;&lt;/ptclib&gt;&lt;/lid.h&gt;&lt;/gsmcodec.h&gt;&lt;/h245.h&gt;&lt;/h323pdu.h&gt;&lt;/h323.h&gt;&lt;/ptlib.h&gt;&lt;/h323.h&gt;&lt;/ptlib.h&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-652287674571376978?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/652287674571376978/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=652287674571376978' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/652287674571376978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/652287674571376978'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/openh323voip.html' title='使用OpenH323开发VOIP程序'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7427153926913253228.post-8988073989025474406</id><published>2007-01-03T16:05:00.000+08:00</published><updated>2007-01-03T16:11:41.390+08:00</updated><title type='text'>It is google blog system?</title><content type='html'>我发现这里面有我多年以前申请的BLOG，就是访问速度太慢了，浪费时间于是就在申请后，再也没有关注过。但是今天不一样了，它属于GOOGLE了，也许会快一些吧，由于我接触的技术范围很广，但是不是很泛泛的意思，可能就是跳跃性比较强的意思吧，最初就是打算收集一些我自己在当时的一些理解，所以申请了那个BLOG。现在的考虑也是包括这个意思，只不过自从10月份辞职以来时间就从容了许多，也许在GOOGLE的大树下我能乘凉一下----把我经历的一些技术问题和所有人分享，节省大家的时间我想也是在创造价值吧。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7427153926913253228-8988073989025474406?l=techresearchinfo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://techresearchinfo.blogspot.com/feeds/8988073989025474406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7427153926913253228&amp;postID=8988073989025474406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8988073989025474406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7427153926913253228/posts/default/8988073989025474406'/><link rel='alternate' type='text/html' href='http://techresearchinfo.blogspot.com/2007/01/it-is-google-blog-system.html' title='It is google blog system?'/><author><name>Guijin Ding</name><uri>http://www.blogger.com/profile/05010248415367642807</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/-fqeSRhtXEO4/TsxzuYflbBI/AAAAAAAAAd4/HlJ_GBLNSAI/s220/IMG_0046.JPG'/></author><thr:total>0</thr:total></entry></feed>
