<?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'><id>tag:blogger.com,1999:blog-5296319277701400211</id><updated>2009-09-26T18:04:34.630-07:00</updated><title type='text'>Serial port communication and programming</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default?start-index=26&amp;max-results=25'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-1707284069815767097</id><published>2008-07-26T22:54:00.000-07:00</published><updated>2008-07-26T22:55:05.935-07:00</updated><title type='text'>LibGW32C for Windows</title><content type='html'>Version&lt;br /&gt;&lt;br /&gt;0.4&lt;br /&gt;Description&lt;br /&gt;&lt;br /&gt;This is an implementation of a small part of GLibC, just enough to compile most Unix programs on MS Windows. It contains functions for passwords, process id's groups, and strings. Most are interfaces to the MS-Windows Win32 API. Some are just dummy functions that do nothing.&lt;br /&gt;&lt;br /&gt;The following functions are provided:&lt;br /&gt;&lt;br /&gt;    * a64l&lt;br /&gt;    * __access&lt;br /&gt;    * access&lt;br /&gt;    * __addmntent&lt;br /&gt;    * addmntent&lt;br /&gt;    * __addmntentstr&lt;br /&gt;    * alarm&lt;br /&gt;    * alphasort&lt;br /&gt;    * alphasort64&lt;br /&gt;    * argp_err_exit_status&lt;br /&gt;    * __argp_error&lt;br /&gt;    * argp_error&lt;br /&gt;    * __argp_failure&lt;br /&gt;    * argp_failure&lt;br /&gt;    * __argp_fmtstream_ensure&lt;br /&gt;    * __argp_fmtstream_free&lt;br /&gt;    * __argp_fmtstream_point&lt;br /&gt;    * __argp_fmtstream_printf&lt;br /&gt;    * __argp_fmtstream_putc&lt;br /&gt;    * __argp_fmtstream_puts&lt;br /&gt;    * __argp_fmtstream_set_lmargin&lt;br /&gt;    * __argp_fmtstream_set_rmargin&lt;br /&gt;    * __argp_fmtstream_set_wmargin&lt;br /&gt;    * __argp_fmtstream_update&lt;br /&gt;    * __argp_fmtstream_write&lt;br /&gt;    * __argp_help&lt;br /&gt;    * argp_help&lt;br /&gt;    * __argp_input&lt;br /&gt;    * _argp_input&lt;br /&gt;    * __argp_make_fmtstream&lt;br /&gt;    * __argp_parse&lt;br /&gt;    * argp_parse&lt;br /&gt;    * argp_program_bug_address&lt;br /&gt;    * argp_program_version&lt;br /&gt;    * argp_program_version_hook&lt;br /&gt;    * __argp_state_help&lt;br /&gt;    * argp_state_help&lt;br /&gt;    * _argp_unlock_xxx&lt;br /&gt;    * __argp_usage&lt;br /&gt;    * argp_usage&lt;br /&gt;    * __argz_add&lt;br /&gt;    * argz_add&lt;br /&gt;    * __argz_add_sep&lt;br /&gt;    * argz_add_sep&lt;br /&gt;    * __argz_append&lt;br /&gt;    * argz_append&lt;br /&gt;    * __argz_count&lt;br /&gt;    * argz_count&lt;br /&gt;    * __argz_create&lt;br /&gt;    * argz_create&lt;br /&gt;    * __argz_create_sep&lt;br /&gt;    * argz_create_sep&lt;br /&gt;    * argz_delete&lt;br /&gt;    * __argz_extract&lt;br /&gt;    * argz_extract&lt;br /&gt;    * __argz_insert&lt;br /&gt;    * argz_insert&lt;br /&gt;    * __argz_next&lt;br /&gt;    * argz_next&lt;br /&gt;    * __argz_replace&lt;br /&gt;    * argz_replace&lt;br /&gt;    * __argz_stringify&lt;br /&gt;    * argz_stringify&lt;br /&gt;    * attr2mode&lt;br /&gt;    * BackupLink&lt;br /&gt;    * basename&lt;br /&gt;    * bcopy&lt;br /&gt;    * __brk&lt;br /&gt;    * brk&lt;br /&gt;    * bsearch&lt;br /&gt;    * __bzero&lt;br /&gt;    * bzero&lt;br /&gt;    * __canonicalize_file_name&lt;br /&gt;    * canonicalize_file_name&lt;br /&gt;    * catclose&lt;br /&gt;    * catgets&lt;br /&gt;    * catopen&lt;br /&gt;    * cfgetispeed&lt;br /&gt;    * cfgetospeed&lt;br /&gt;    * cfmakeraw&lt;br /&gt;    * cfsetispeed&lt;br /&gt;    * cfsetospeed&lt;br /&gt;    * cfsetspeed&lt;br /&gt;    * __chdir&lt;br /&gt;    * chdir&lt;br /&gt;    * chflags&lt;br /&gt;    * __chown&lt;br /&gt;    * chown&lt;br /&gt;    * chroot&lt;br /&gt;    * clock&lt;br /&gt;    * clock_getcpuclockid&lt;br /&gt;    * clock_getres&lt;br /&gt;    * clock_gettime&lt;br /&gt;    * clock_nanosleep&lt;br /&gt;    * clock_settime&lt;br /&gt;    * __closedir&lt;br /&gt;    * closedir&lt;br /&gt;    * CreateLink&lt;br /&gt;    * crypt&lt;br /&gt;    * __crypt_r&lt;br /&gt;    * crypt_r&lt;br /&gt;    * __curbrk&lt;br /&gt;    * cuserid&lt;br /&gt;    * __cxstat64&lt;br /&gt;    * debugprint&lt;br /&gt;    * DecodeError&lt;br /&gt;    * devrootdir&lt;br /&gt;    * dirfd&lt;br /&gt;    * dirname&lt;br /&gt;    * dladdr&lt;br /&gt;    * dlclose&lt;br /&gt;    * dlerror&lt;br /&gt;    * dlopen&lt;br /&gt;    * dlsym&lt;br /&gt;    * __dlvsym&lt;br /&gt;    * dlvsym&lt;br /&gt;    * drand48&lt;br /&gt;    * __drand48_iterate&lt;br /&gt;    * drand48_r&lt;br /&gt;    * ecvt&lt;br /&gt;    * ecvt_r&lt;br /&gt;    * encrypt&lt;br /&gt;    * __encrypt_r&lt;br /&gt;    * encrypt_r&lt;br /&gt;    * endfsent&lt;br /&gt;    * endgrent&lt;br /&gt;    * endhostent&lt;br /&gt;    * __endmntent&lt;br /&gt;    * endmntent&lt;br /&gt;    * endpwent&lt;br /&gt;    * endusershell&lt;br /&gt;    * envz_add&lt;br /&gt;    * envz_entry&lt;br /&gt;    * envz_get&lt;br /&gt;    * envz_merge&lt;br /&gt;    * envz_remove&lt;br /&gt;    * envz_strip&lt;br /&gt;    * erand48&lt;br /&gt;    * __erand48_r&lt;br /&gt;    * erand48_r&lt;br /&gt;    * err&lt;br /&gt;    * __error&lt;br /&gt;    * error&lt;br /&gt;    * __error_at_line&lt;br /&gt;    * error_at_line&lt;br /&gt;    * error_message_count&lt;br /&gt;    * error_one_per_line&lt;br /&gt;    * error_print_progname&lt;br /&gt;    * errx&lt;br /&gt;    * __euidaccess&lt;br /&gt;    * euidaccess&lt;br /&gt;    * __fchdir&lt;br /&gt;    * fchdir&lt;br /&gt;    * fchflags&lt;br /&gt;    * __fchmod&lt;br /&gt;    * fchmod&lt;br /&gt;    * __fchown&lt;br /&gt;    * fchown&lt;br /&gt;    * __fcntl&lt;br /&gt;    * fcntl&lt;br /&gt;    * fcrypt&lt;br /&gt;    * fcvt&lt;br /&gt;    * fcvt_r&lt;br /&gt;    * fdatasync&lt;br /&gt;    * fesetround&lt;br /&gt;    * __ffs&lt;br /&gt;    * ffs&lt;br /&gt;    * ffsl&lt;br /&gt;    * fgetxattr&lt;br /&gt;    * file_exists&lt;br /&gt;    * FileInformationToStat64&lt;br /&gt;    * flistxattr&lt;br /&gt;    * __flockfile&lt;br /&gt;    * flockfile&lt;br /&gt;    * __fork&lt;br /&gt;    * fork&lt;br /&gt;    * __fpathconf&lt;br /&gt;    * fpathconf&lt;br /&gt;    * fremovexattr&lt;br /&gt;    * frootdir&lt;br /&gt;    * fseeko&lt;br /&gt;    * fseeko64&lt;br /&gt;    * __fsetlocking&lt;br /&gt;    * fsetxattr&lt;br /&gt;    * __fstat&lt;br /&gt;    * fstat&lt;br /&gt;    * fstat64&lt;br /&gt;    * __fstatfs&lt;br /&gt;    * fstatfs&lt;br /&gt;    * __fstatfs64&lt;br /&gt;    * fstatfs64&lt;br /&gt;    * __fstatvfs&lt;br /&gt;    * fstatvfs&lt;br /&gt;    * __fstatvfs64&lt;br /&gt;    * fstatvfs64&lt;br /&gt;    * ftello&lt;br /&gt;    * ftello64&lt;br /&gt;    * __ftruncate&lt;br /&gt;    * ftruncate&lt;br /&gt;    * __ftruncate64&lt;br /&gt;    * ftruncate64&lt;br /&gt;    * __ftrylockfile&lt;br /&gt;    * ftrylockfile&lt;br /&gt;    * fts_children&lt;br /&gt;    * fts_close&lt;br /&gt;    * fts_open&lt;br /&gt;    * fts_read&lt;br /&gt;    * fts_set&lt;br /&gt;    * ftw&lt;br /&gt;    * ftw64&lt;br /&gt;    * __funlockfile&lt;br /&gt;    * funlockfile&lt;br /&gt;    * __futimes&lt;br /&gt;    * futimes&lt;br /&gt;    * __fxstat&lt;br /&gt;    * _fxstat&lt;br /&gt;    * __fxstat64&lt;br /&gt;    * gcvt&lt;br /&gt;    * __gen_tempname&lt;br /&gt;    * __get_avphys_pages&lt;br /&gt;    * get_avphys_pages&lt;br /&gt;    * __get_clockfreq&lt;br /&gt;    * get_current_dir_name&lt;br /&gt;    * __get_errno&lt;br /&gt;    * __get_nprocs&lt;br /&gt;    * get_nprocs&lt;br /&gt;    * __get_nprocs_conf&lt;br /&gt;    * get_nprocs_conf&lt;br /&gt;    * __get_phys_pages&lt;br /&gt;    * get_phys_pages&lt;br /&gt;    * __getclktck&lt;br /&gt;    * getcpuspeed&lt;br /&gt;    * __getcwd&lt;br /&gt;    * getdomainname&lt;br /&gt;    * __getdtablesize&lt;br /&gt;    * getdtablesize&lt;br /&gt;    * __getegid&lt;br /&gt;    * getegid&lt;br /&gt;    * __geteuid&lt;br /&gt;    * geteuid&lt;br /&gt;    * getexecdir&lt;br /&gt;    * getexecparent&lt;br /&gt;    * getexecpath&lt;br /&gt;    * GetFileAttributeData&lt;br /&gt;    * GetFileInformationByName&lt;br /&gt;    * getfsent&lt;br /&gt;    * getfsfile&lt;br /&gt;    * getfsspec&lt;br /&gt;    * __getgid&lt;br /&gt;    * getgid&lt;br /&gt;    * getgranularity&lt;br /&gt;    * getgrent&lt;br /&gt;    * getgrent_r&lt;br /&gt;    * getgrgid&lt;br /&gt;    * getgrnam&lt;br /&gt;    * __getgroups&lt;br /&gt;    * getgroups&lt;br /&gt;    * gethostent&lt;br /&gt;    * gethostid&lt;br /&gt;    * __getline&lt;br /&gt;    * getline&lt;br /&gt;    * getloadavg&lt;br /&gt;    * getlogin&lt;br /&gt;    * getlongpath&lt;br /&gt;    * GetMachInfo&lt;br /&gt;    * getmntent&lt;br /&gt;    * __getmntent_r&lt;br /&gt;    * getmntent_r&lt;br /&gt;    * __getntptimeofday&lt;br /&gt;    * getntptimeofday&lt;br /&gt;    * getopt&lt;br /&gt;    * __getopt_initialized&lt;br /&gt;    * _getopt_internal&lt;br /&gt;    * getopt_long&lt;br /&gt;    * getopt_long_only&lt;br /&gt;    * GetOsInfo&lt;br /&gt;    * __getpagesize&lt;br /&gt;    * getpagesize&lt;br /&gt;    * getpass&lt;br /&gt;    * __getpgid&lt;br /&gt;    * getpgid&lt;br /&gt;    * getpgrp&lt;br /&gt;    * __getppid&lt;br /&gt;    * getppid&lt;br /&gt;    * getpriority&lt;br /&gt;    * getprogname&lt;br /&gt;    * getpwent&lt;br /&gt;    * getpwnam&lt;br /&gt;    * getpwuid&lt;br /&gt;    * __getrlimit&lt;br /&gt;    * getrlimit&lt;br /&gt;    * __getrlimit64&lt;br /&gt;    * getrlimit64&lt;br /&gt;    * getrootdirs&lt;br /&gt;    * getshortpath&lt;br /&gt;    * getsid&lt;br /&gt;    * GetStat64ByHandle&lt;br /&gt;    * GetStat64ByName&lt;br /&gt;    * __gettimeofday&lt;br /&gt;    * gettimeofday&lt;br /&gt;    * __getuid&lt;br /&gt;    * getuid&lt;br /&gt;    * getuname&lt;br /&gt;    * getusershell&lt;br /&gt;    * GetVendorID&lt;br /&gt;    * GetVolumeSerialNumber&lt;br /&gt;    * getwd&lt;br /&gt;    * getxattr&lt;br /&gt;    * GetXStat64ByName&lt;br /&gt;    * __group_member&lt;br /&gt;    * group_member&lt;br /&gt;    * gtty&lt;br /&gt;    * handle2mode&lt;br /&gt;    * hashval&lt;br /&gt;    * __hasmntopt&lt;br /&gt;    * hasmntopt&lt;br /&gt;    * hcreate&lt;br /&gt;    * hcreate_r&lt;br /&gt;    * __hdestroy&lt;br /&gt;    * hdestroy&lt;br /&gt;    * hdestroy_r&lt;br /&gt;    * hsearch&lt;br /&gt;    * hsearch_r&lt;br /&gt;    * __hutimes&lt;br /&gt;    * __init_des&lt;br /&gt;    * __init_des_r&lt;br /&gt;    * __init_misc&lt;br /&gt;    * __initstate&lt;br /&gt;    * initstate&lt;br /&gt;    * __initstate_r&lt;br /&gt;    * initstate_r&lt;br /&gt;    * insque&lt;br /&gt;    * _IO_flockfile&lt;br /&gt;    * _IO_ftrylockfile&lt;br /&gt;    * _IO_funlockfile&lt;br /&gt;    * __ioctl&lt;br /&gt;    * ioctl&lt;br /&gt;    * issymlink&lt;br /&gt;    * IsWin31&lt;br /&gt;    * IsWin9x&lt;br /&gt;    * IsWinCE&lt;br /&gt;    * IsWinNT&lt;br /&gt;    * _itoa_lower_digits&lt;br /&gt;    * _itoa_upper_digits&lt;br /&gt;    * jrand48&lt;br /&gt;    * __jrand48_r&lt;br /&gt;    * jrand48_r&lt;br /&gt;    * __kill&lt;br /&gt;    * kill&lt;br /&gt;    * l64a&lt;br /&gt;    * lchmod&lt;br /&gt;    * __lchown&lt;br /&gt;    * lchown&lt;br /&gt;    * lcong48&lt;br /&gt;    * __lcong48_r&lt;br /&gt;    * lcong48_r&lt;br /&gt;    * lfind&lt;br /&gt;    * lgetxattr&lt;br /&gt;    * __libc_drand48_data&lt;br /&gt;    * __libc_enable_secure&lt;br /&gt;    * __libc_init&lt;br /&gt;    * __libc_init_first&lt;br /&gt;    * __libc_init_secure&lt;br /&gt;    * _libc_intl_domainname&lt;br /&gt;    * __libc_multiple_libcs&lt;br /&gt;    * __libc_nanosleep&lt;br /&gt;    * __libc_readv&lt;br /&gt;    * __libc_tcdrain&lt;br /&gt;    * __libc_tsd_LOCALE_data&lt;br /&gt;    * __libc_wait&lt;br /&gt;    * __libc_waitid&lt;br /&gt;    * __libc_waitpid&lt;br /&gt;    * __link&lt;br /&gt;    * link&lt;br /&gt;    * listxattr&lt;br /&gt;    * llistxattr&lt;br /&gt;    * lock&lt;br /&gt;    * lock64&lt;br /&gt;    * lrand48&lt;br /&gt;    * lrand48_r&lt;br /&gt;    * lremovexattr&lt;br /&gt;    * lsearch&lt;br /&gt;    * lsetxattr&lt;br /&gt;    * __lstat&lt;br /&gt;    * lstat&lt;br /&gt;    * lstat64&lt;br /&gt;    * __lutimes&lt;br /&gt;    * lutimes&lt;br /&gt;    * __lxstat&lt;br /&gt;    * _lxstat&lt;br /&gt;    * __lxstat64&lt;br /&gt;    * madvise&lt;br /&gt;    * __md5_buffer&lt;br /&gt;    * __md5_crypt&lt;br /&gt;    * __md5_crypt_r&lt;br /&gt;    * __md5_finish_ctx&lt;br /&gt;    * __md5_init_ctx&lt;br /&gt;    * __md5_process_block&lt;br /&gt;    * __md5_process_bytes&lt;br /&gt;    * __md5_read_ctx&lt;br /&gt;    * __md5_stream&lt;br /&gt;    * memfrob&lt;br /&gt;    * __mempcpy&lt;br /&gt;    * mempcpy&lt;br /&gt;    * __memrchr&lt;br /&gt;    * memrchr&lt;br /&gt;    * __mkdir&lt;br /&gt;    * mkdir&lt;br /&gt;    * mkdtemp&lt;br /&gt;    * mkfifo&lt;br /&gt;    * __mknod&lt;br /&gt;    * mknod&lt;br /&gt;    * mkstemp64&lt;br /&gt;    * mkstemps&lt;br /&gt;    * mktemp&lt;br /&gt;    * mlock&lt;br /&gt;    * mlockall&lt;br /&gt;    * __mmap&lt;br /&gt;    * mmap&lt;br /&gt;    * __mmap64&lt;br /&gt;    * mmap64&lt;br /&gt;    * mode2osflags&lt;br /&gt;    * __mpn_lshift&lt;br /&gt;    * __mpn_rshift&lt;br /&gt;    * __mprotect&lt;br /&gt;    * mprotect&lt;br /&gt;    * mrand48&lt;br /&gt;    * mrand48_r&lt;br /&gt;    * mremap&lt;br /&gt;    * msync&lt;br /&gt;    * mtrace&lt;br /&gt;    * munlock&lt;br /&gt;    * munlockall&lt;br /&gt;    * __munmap&lt;br /&gt;    * munmap&lt;br /&gt;    * muntrace&lt;br /&gt;    * __nanosleep&lt;br /&gt;    * nanosleep&lt;br /&gt;    * nftw&lt;br /&gt;    * nftw64&lt;br /&gt;    * nice&lt;br /&gt;    * _nl_C_codeset&lt;br /&gt;    * _nl_C_LC_ADDRESS&lt;br /&gt;    * _nl_C_LC_COLLATE&lt;br /&gt;    * _nl_C_LC_CTYPE&lt;br /&gt;    * _nl_C_LC_CTYPE_class&lt;br /&gt;    * _nl_C_LC_CTYPE_class32&lt;br /&gt;    * _nl_C_LC_CTYPE_class_alnum&lt;br /&gt;    * _nl_C_LC_CTYPE_class_alpha&lt;br /&gt;    * _nl_C_LC_CTYPE_class_blank&lt;br /&gt;    * _nl_C_LC_CTYPE_class_cntrl&lt;br /&gt;    * _nl_C_LC_CTYPE_class_digit&lt;br /&gt;    * _nl_C_LC_CTYPE_class_graph&lt;br /&gt;    * _nl_C_LC_CTYPE_class_lower&lt;br /&gt;    * _nl_C_LC_CTYPE_class_print&lt;br /&gt;    * _nl_C_LC_CTYPE_class_punct&lt;br /&gt;    * _nl_C_LC_CTYPE_class_space&lt;br /&gt;    * _nl_C_LC_CTYPE_class_upper&lt;br /&gt;    * _nl_C_LC_CTYPE_class_xdigit&lt;br /&gt;    * _nl_C_LC_CTYPE_map_tolower&lt;br /&gt;    * _nl_C_LC_CTYPE_map_toupper&lt;br /&gt;    * _nl_C_LC_CTYPE_tolower&lt;br /&gt;    * _nl_C_LC_CTYPE_toupper&lt;br /&gt;    * _nl_C_LC_CTYPE_width&lt;br /&gt;    * _nl_C_LC_IDENTIFICATION&lt;br /&gt;    * _nl_C_LC_MEASUREMENT&lt;br /&gt;    * _nl_C_LC_MESSAGES&lt;br /&gt;    * _nl_C_LC_MONETARY&lt;br /&gt;    * _nl_C_LC_NAME&lt;br /&gt;    * _nl_C_LC_NUMERIC&lt;br /&gt;    * _nl_C_LC_PAPER&lt;br /&gt;    * _nl_C_LC_TELEPHONE&lt;br /&gt;    * _nl_C_LC_TIME&lt;br /&gt;    * _nl_C_name&lt;br /&gt;    * _nl_global_locale&lt;br /&gt;    * nl_langinfo&lt;br /&gt;    * _nl_POSIX_name&lt;br /&gt;    * nrand48&lt;br /&gt;    * __nrand48_r&lt;br /&gt;    * nrand48_r&lt;br /&gt;    * __open_catalog&lt;br /&gt;    * __opendir&lt;br /&gt;    * opendir&lt;br /&gt;    * optarg&lt;br /&gt;    * opterr&lt;br /&gt;    * optind&lt;br /&gt;    * __option_is_end&lt;br /&gt;    * _option_is_end&lt;br /&gt;    * __option_is_short&lt;br /&gt;    * _option_is_short&lt;br /&gt;    * optopt&lt;br /&gt;    * osflags2mode&lt;br /&gt;    * path2mode&lt;br /&gt;    * __path_search&lt;br /&gt;    * __pathconf&lt;br /&gt;    * pathconf&lt;br /&gt;    * __pipe&lt;br /&gt;    * pipe&lt;br /&gt;    * posix2winfullpath&lt;br /&gt;    * posix2winpath&lt;br /&gt;    * posix_madvise&lt;br /&gt;    * posix_mremap&lt;br /&gt;    * PrintWinErr&lt;br /&gt;    * __progname&lt;br /&gt;    * __progname_full&lt;br /&gt;    * program_invocation_name&lt;br /&gt;    * program_invocation_short_name&lt;br /&gt;    * program_name&lt;br /&gt;    * __pthread_clock_gettime&lt;br /&gt;    * __pthread_clock_settime&lt;br /&gt;    * qecvt&lt;br /&gt;    * qecvt_r&lt;br /&gt;    * qfcvt&lt;br /&gt;    * qfcvt_r&lt;br /&gt;    * qgcvt&lt;br /&gt;    * qsort&lt;br /&gt;    * _quicksort&lt;br /&gt;    * rand&lt;br /&gt;    * rand_r&lt;br /&gt;    * __random&lt;br /&gt;    * random&lt;br /&gt;    * __random_r&lt;br /&gt;    * random_r&lt;br /&gt;    * __rawmemchr&lt;br /&gt;    * rawmemchr&lt;br /&gt;    * __readdir&lt;br /&gt;    * readdir&lt;br /&gt;    * __readdir64&lt;br /&gt;    * readdir64&lt;br /&gt;    * __readdir64_r&lt;br /&gt;    * readdir64_r&lt;br /&gt;    * __readdir_r&lt;br /&gt;    * readdir_r&lt;br /&gt;    * readlink&lt;br /&gt;    * __readv&lt;br /&gt;    * readv&lt;br /&gt;    * __realpath&lt;br /&gt;    * realpath&lt;br /&gt;    * remove&lt;br /&gt;    * removexattr&lt;br /&gt;    * remque&lt;br /&gt;    * rename&lt;br /&gt;    * ResolveLink&lt;br /&gt;    * __rewinddir&lt;br /&gt;    * rewinddir&lt;br /&gt;    * __rmdir&lt;br /&gt;    * rmdir&lt;br /&gt;    * rootdir&lt;br /&gt;    * __rstatfsx64&lt;br /&gt;    * __sbrk&lt;br /&gt;    * sbrk&lt;br /&gt;    * scandir&lt;br /&gt;    * scandir64&lt;br /&gt;    * __secure_getenv&lt;br /&gt;    * seed48&lt;br /&gt;    * __seed48_r&lt;br /&gt;    * seed48_r&lt;br /&gt;    * __seekdir&lt;br /&gt;    * seekdir&lt;br /&gt;    * __select&lt;br /&gt;    * select&lt;br /&gt;    * setdomainname&lt;br /&gt;    * setegid&lt;br /&gt;    * setenv&lt;br /&gt;    * setfsent&lt;br /&gt;    * setgid&lt;br /&gt;    * setgrent&lt;br /&gt;    * sethostent&lt;br /&gt;    * sethostid&lt;br /&gt;    * sethostname&lt;br /&gt;    * setkey&lt;br /&gt;    * __setkey_r&lt;br /&gt;    * setkey_r&lt;br /&gt;    * setlogin&lt;br /&gt;    * __setmntent&lt;br /&gt;    * setmntent&lt;br /&gt;    * __setntptimeofday&lt;br /&gt;    * setntptimeofday&lt;br /&gt;    * __setpgid&lt;br /&gt;    * setpgid&lt;br /&gt;    * setpgrp&lt;br /&gt;    * setpriority&lt;br /&gt;    * setpwent&lt;br /&gt;    * __setregid&lt;br /&gt;    * setregid&lt;br /&gt;    * __setreuid&lt;br /&gt;    * setreuid&lt;br /&gt;    * __setrlimit&lt;br /&gt;    * setrlimit&lt;br /&gt;    * __setrlimit64&lt;br /&gt;    * setrlimit64&lt;br /&gt;    * __setstate&lt;br /&gt;    * setstate&lt;br /&gt;    * __setstate_r&lt;br /&gt;    * setstate_r&lt;br /&gt;    * __settimeofday&lt;br /&gt;    * settimeofday&lt;br /&gt;    * setuid&lt;br /&gt;    * setusershell&lt;br /&gt;    * setxattr&lt;br /&gt;    * __sigaction&lt;br /&gt;    * sigaction&lt;br /&gt;    * __sigaddset&lt;br /&gt;    * sigaddset&lt;br /&gt;    * sigfillset&lt;br /&gt;    * __sigprocmask&lt;br /&gt;    * sigprocmask&lt;br /&gt;    * __sleep&lt;br /&gt;    * sleep&lt;br /&gt;    * _splitpath&lt;br /&gt;    * srand&lt;br /&gt;    * srand48&lt;br /&gt;    * __srand48_r&lt;br /&gt;    * srand48_r&lt;br /&gt;    * __srandom&lt;br /&gt;    * srandom&lt;br /&gt;    * __srandom_r&lt;br /&gt;    * srandom_r&lt;br /&gt;    * __stat&lt;br /&gt;    * stat&lt;br /&gt;    * __stat64&lt;br /&gt;    * stat64&lt;br /&gt;    * stat64_to_32&lt;br /&gt;    * __statfs&lt;br /&gt;    * statfs&lt;br /&gt;    * __statfs64&lt;br /&gt;    * statfs64&lt;br /&gt;    * __statfsbsd&lt;br /&gt;    * statfsbsd&lt;br /&gt;    * __statfsx64&lt;br /&gt;    * statfsx64&lt;br /&gt;    * __statvfs&lt;br /&gt;    * statvfs&lt;br /&gt;    * __statvfs64&lt;br /&gt;    * statvfs64&lt;br /&gt;    * __stpcpy&lt;br /&gt;    * stpcpy&lt;br /&gt;    * __stpncpy&lt;br /&gt;    * stpncpy&lt;br /&gt;    * __strchrnul&lt;br /&gt;    * strchrnul&lt;br /&gt;    * __strerror_r&lt;br /&gt;    * strerror_r&lt;br /&gt;    * strfry&lt;br /&gt;    * strlcat&lt;br /&gt;    * strlcpy&lt;br /&gt;    * strmode&lt;br /&gt;    * __strncasecmp&lt;br /&gt;    * strncasecmp&lt;br /&gt;    * __strndup&lt;br /&gt;    * strndup&lt;br /&gt;    * __strnlen&lt;br /&gt;    * strnlen&lt;br /&gt;    * strptime&lt;br /&gt;    * __strsep&lt;br /&gt;    * strsep&lt;br /&gt;    * __strsep_g&lt;br /&gt;    * strsignal&lt;br /&gt;    * __strtok_r&lt;br /&gt;    * strtok_r&lt;br /&gt;    * __strverscmp&lt;br /&gt;    * strverscmp&lt;br /&gt;    * symlink&lt;br /&gt;    * sync&lt;br /&gt;    * _sys_errlist_internal&lt;br /&gt;    * _sys_nerr_internal&lt;br /&gt;    * _sys_siglist&lt;br /&gt;    * sys_siglist&lt;br /&gt;    * _sys_siglist_internal&lt;br /&gt;    * syscall&lt;br /&gt;    * __sysconf&lt;br /&gt;    * sysconf&lt;br /&gt;    * sysinfo&lt;br /&gt;    * tcdrain&lt;br /&gt;    * tcflow&lt;br /&gt;    * tcflush&lt;br /&gt;    * __tcgetattr&lt;br /&gt;    * tcgetattr&lt;br /&gt;    * tcgetpgrp&lt;br /&gt;    * tcgetsid&lt;br /&gt;    * tcsendbreak&lt;br /&gt;    * tcsetattr&lt;br /&gt;    * tcsetpgrp&lt;br /&gt;    * __tdelete&lt;br /&gt;    * tdelete&lt;br /&gt;    * __tdestroy&lt;br /&gt;    * tdestroy&lt;br /&gt;    * __telldir&lt;br /&gt;    * telldir&lt;br /&gt;    * tempnam&lt;br /&gt;    * __tfind&lt;br /&gt;    * tfind&lt;br /&gt;    * __times&lt;br /&gt;    * times&lt;br /&gt;    * tm_year_base&lt;br /&gt;    * tmpfile&lt;br /&gt;    * tmpfile64&lt;br /&gt;    * tmpnam&lt;br /&gt;    * tmpnam_r&lt;br /&gt;    * __truncate&lt;br /&gt;    * truncate&lt;br /&gt;    * __truncate64&lt;br /&gt;    * truncate64&lt;br /&gt;    * __tsearch&lt;br /&gt;    * tsearch&lt;br /&gt;    * ttyname&lt;br /&gt;    * __twalk&lt;br /&gt;    * twalk&lt;br /&gt;    * __tzname_cur_max&lt;br /&gt;    * __tzname_max&lt;br /&gt;    * _ufc_dofinalperm_r&lt;br /&gt;    * _ufc_doit_r&lt;br /&gt;    * _ufc_foobar&lt;br /&gt;    * _ufc_mk_keytab_r&lt;br /&gt;    * _ufc_output_conversion_r&lt;br /&gt;    * _ufc_setup_salt_r&lt;br /&gt;    * __ulimit&lt;br /&gt;    * ulimit&lt;br /&gt;    * __uname&lt;br /&gt;    * uname&lt;br /&gt;    * unix2winpath&lt;br /&gt;    * __unlink&lt;br /&gt;    * unlink&lt;br /&gt;    * unsetenv&lt;br /&gt;    * usleep&lt;br /&gt;    * ustat&lt;br /&gt;    * utime&lt;br /&gt;    * __utimes&lt;br /&gt;    * utimes&lt;br /&gt;    * verr&lt;br /&gt;    * verrx&lt;br /&gt;    * versionsort&lt;br /&gt;    * versionsort64&lt;br /&gt;    * vlimit&lt;br /&gt;    * vsn2drive&lt;br /&gt;    * vwarn&lt;br /&gt;    * vwarnx&lt;br /&gt;    * __w32_gethostbyaddr&lt;br /&gt;    * w32_gethostbyaddr&lt;br /&gt;    * __w32_gethostbyname&lt;br /&gt;    * w32_gethostbyname&lt;br /&gt;    * __w32_gethostname&lt;br /&gt;    * w32_gethostname&lt;br /&gt;    * w32_same_file&lt;br /&gt;    * __wait&lt;br /&gt;    * wait&lt;br /&gt;    * __wait3&lt;br /&gt;    * wait3&lt;br /&gt;    * __wait4&lt;br /&gt;    * wait4&lt;br /&gt;    * __waitid&lt;br /&gt;    * waitid&lt;br /&gt;    * __waitpid&lt;br /&gt;    * waitpid&lt;br /&gt;    * warn&lt;br /&gt;    * warnx&lt;br /&gt;    * werrno&lt;br /&gt;    * win2posixfullpath&lt;br /&gt;    * win2posixpath&lt;br /&gt;    * win2unixpath&lt;br /&gt;    * win32_longpath&lt;br /&gt;    * WinErr&lt;br /&gt;    * winmajor&lt;br /&gt;    * winminor&lt;br /&gt;    * winos&lt;br /&gt;    * winplatform&lt;br /&gt;    * _wordcopy_bwd_aligned&lt;br /&gt;    * _wordcopy_bwd_dest_aligned&lt;br /&gt;    * _wordcopy_fwd_aligned&lt;br /&gt;    * _wordcopy_fwd_dest_aligned&lt;br /&gt;    * ws_cleanup&lt;br /&gt;    * ws_init&lt;br /&gt;    * WSAErr&lt;br /&gt;    * __xmknod&lt;br /&gt;    * _xmknod&lt;br /&gt;    * __xpg_basename&lt;br /&gt;    * __xstat&lt;br /&gt;    * _xstat&lt;br /&gt;    * __xstat64 &lt;br /&gt;&lt;br /&gt;The documentation of most of these functions is in the Glibc-documentation, in the Linux manpages and in the FreeBsd manpages.&lt;br /&gt;Homepage&lt;br /&gt;&lt;br /&gt;http://www.gnu.org/software/libc/libc.html&lt;br /&gt;&lt;br /&gt;Sources:&lt;br /&gt;Download&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;Description  Download  Size  Last change  Md5sum&lt;br /&gt; &lt;br /&gt;• Developer files   Zip    643174   10 January 2004    55b41650239b13d2b0d79c100d160665&lt;br /&gt;• Sources   Zip    2226097   10 January 2004    f8c7c821033c9ed141c347edf3c30477&lt;br /&gt;• Original source  &lt;br /&gt;&lt;br /&gt;You can also download the files from the GnuWin32 files page. New releases of the port of this package can be monitored.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-1707284069815767097?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/1707284069815767097/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=1707284069815767097' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1707284069815767097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1707284069815767097'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/07/libgw32c-for-windows.html' title='LibGW32C for Windows'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-8811761996009683168</id><published>2008-07-23T21:43:00.000-07:00</published><updated>2008-07-23T21:44:04.827-07:00</updated><title type='text'>SSH Connection Protocol</title><content type='html'>Status of This memo&lt;br /&gt;&lt;br /&gt;This document is an Internet-Draft and is in full conformance&lt;br /&gt;with all provisions of Section 10 of RFC2026.&lt;br /&gt;&lt;br /&gt;Internet-Drafts are working documents of the Internet Engineering&lt;br /&gt;Task Force (IETF), its areas, and its working groups.  Note that&lt;br /&gt;other groups may also distribute working documents as&lt;br /&gt;Internet-Drafts.&lt;br /&gt;&lt;br /&gt;Internet-Drafts are draft documents valid for a maximum of six&lt;br /&gt;months and may be updated, replaced, or obsoleted by other&lt;br /&gt;documents at any time.  It is inappropriate to use Internet-&lt;br /&gt;Drafts as reference material or to cite them other than as&lt;br /&gt;"work in progress."&lt;br /&gt;&lt;br /&gt;The list of current Internet-Drafts can be accessed at&lt;br /&gt;http://www.ietf.org/ietf/1id-abstracts.txt&lt;br /&gt;&lt;br /&gt;The list of Internet-Draft Shadow Directories can be accessed at&lt;br /&gt;http://www.ietf.org/shadow.html.&lt;br /&gt;&lt;br /&gt;Abstract&lt;br /&gt;&lt;br /&gt;SSH is a protocol for secure remote login and other secure network ser-&lt;br /&gt;vices over an insecure network. This document describes the SSH Connec-&lt;br /&gt;tion Protocol. It provides interactive login sessions, remote execution&lt;br /&gt;of commands, forwarded TCP/IP connections, and forwarded X11 connec-&lt;br /&gt;tions. All of these channels are multiplexed into a single encrypted&lt;br /&gt;tunnel.  The SSH Connection Protocol has been designed to run on top of&lt;br /&gt;the SSH transport layer and user authentication protocols.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 1]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;Table of Contents&lt;br /&gt;&lt;br /&gt;1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . . . .  2&lt;br /&gt;2.  Global Requests   . . . . . . . . . . . . . . . . . . . . . . . .  2&lt;br /&gt;3.  Channel Mechanism   . . . . . . . . . . . . . . . . . . . . . . .  3&lt;br /&gt;  3.1.  Opening a Channel   . . . . . . . . . . . . . . . . . . . . .  3&lt;br /&gt;  3.2.  Data Transfer   . . . . . . . . . . . . . . . . . . . . . . .  4&lt;br /&gt;  3.3.  Closing a Channel   . . . . . . . . . . . . . . . . . . . . .  5&lt;br /&gt;  3.4.  Channel-Specific Requests   . . . . . . . . . . . . . . . . .  5&lt;br /&gt;4.  Interactive Sessions  . . . . . . . . . . . . . . . . . . . . . .  6&lt;br /&gt;  4.1.  Opening a Session   . . . . . . . . . . . . . . . . . . . . .  6&lt;br /&gt;  4.2.  Requesting a Pseudo-Terminal  . . . . . . . . . . . . . . . .  6&lt;br /&gt;  4.3.  X11 Forwarding  . . . . . . . . . . . . . . . . . . . . . . .  7&lt;br /&gt;    4.3.1.  Requesting X11 Forwarding   . . . . . . . . . . . . . . .  7&lt;br /&gt;    4.3.2.  X11 Channels  . . . . . . . . . . . . . . . . . . . . . .  8&lt;br /&gt;  4.4.  Environment Variable Passing  . . . . . . . . . . . . . . . .  8&lt;br /&gt;  4.5.  Starting a Shell or a Command   . . . . . . . . . . . . . . .  8&lt;br /&gt;  4.6.  Session Data Transfer   . . . . . . . . . . . . . . . . . . .  9&lt;br /&gt;  4.7.  Window Dimension Change Message   . . . . . . . . . . . . . .  9&lt;br /&gt;  4.8.  Local Flow Control  . . . . . . . . . . . . . . . . . . . . .  9&lt;br /&gt;  4.9.  Signals   . . . . . . . . . . . . . . . . . . . . . . . . . . 10&lt;br /&gt;  4.10.  Returning Exit Status  . . . . . . . . . . . . . . . . . . . 10&lt;br /&gt;5.  TCP/IP Port Forwarding  . . . . . . . . . . . . . . . . . . . . . 11&lt;br /&gt;  5.1.  Requesting Port Forwarding  . . . . . . . . . . . . . . . . . 11&lt;br /&gt;  5.2.  TCP/IP Forwarding Channels  . . . . . . . . . . . . . . . . . 12&lt;br /&gt;6.  Encoding of Terminal Modes  . . . . . . . . . . . . . . . . . . . 13&lt;br /&gt;7.  Summary of Message Numbers  . . . . . . . . . . . . . . . . . . . 15&lt;br /&gt;8.  Security Considerations   . . . . . . . . . . . . . . . . . . . . 15&lt;br /&gt;9.  Trademark Issues  . . . . . . . . . . . . . . . . . . . . . . . . 16&lt;br /&gt;10.  References   . . . . . . . . . . . . . . . . . . . . . . . . . . 16&lt;br /&gt;11.  Authors' Addresses   . . . . . . . . . . . . . . . . . . . . . . 16&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1.  Introduction&lt;br /&gt;&lt;br /&gt;The SSH Connection Protocol has been designed to run on top of the SSH&lt;br /&gt;transport layer and user authentication protocols. It provides&lt;br /&gt;interactive login sessions, remote execution of commands, forwarded&lt;br /&gt;TCP/IP connections, and forwarded X11 connections.  The service name for&lt;br /&gt;this protocol (after user authentication) is "ssh-connection".&lt;br /&gt;&lt;br /&gt;This document should be read only after reading the SSH architecture&lt;br /&gt;document [SSH-ARCH]. This document freely uses terminology and notation&lt;br /&gt;from the architecture document without reference or further explanation.&lt;br /&gt;&lt;br /&gt;2.  Global Requests&lt;br /&gt;&lt;br /&gt;There are several kinds of requests that affect the state of the remote&lt;br /&gt;end "globally", independent of any channels.  An example is a request to&lt;br /&gt;start TCP/IP forwarding for a specific port.  All such requests use the&lt;br /&gt;following format.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 2]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;  byte      SSH_MSG_GLOBAL_REQUEST&lt;br /&gt;  string    request name (restricted to US-ASCII)&lt;br /&gt;  boolean   want reply&lt;br /&gt;  ... request-specific data follows&lt;br /&gt;&lt;br /&gt;The recipient will respond to this message with SSH_MSG_REQUEST_SUCCESS,&lt;br /&gt;SSH_MSG_REQUEST_FAILURE, or some request-specific continuation messages&lt;br /&gt;if `want reply' is TRUE.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_REQUEST_SUCCESS&lt;br /&gt;&lt;br /&gt;If the recipient does not recognize or support the request, it simply&lt;br /&gt;responds with SSH_MSG_REQUEST_FAILURE.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_REQUEST_FAILURE&lt;br /&gt;&lt;br /&gt;3.  Channel Mechanism&lt;br /&gt;&lt;br /&gt;All terminal sessions, forwarded connections, etc. are channels.  Either&lt;br /&gt;side may open a channel.  Multiple channels are multiplexed into a&lt;br /&gt;single connection.&lt;br /&gt;&lt;br /&gt;Channels are identified by numbers at each end.  The number referring to&lt;br /&gt;a channel may be different on each side.  Requests to open a channel&lt;br /&gt;contain the sender's channel number.  Any other channel-related messages&lt;br /&gt;contain the recipient's channel number for the channel.&lt;br /&gt;&lt;br /&gt;Channels are flow-controlled.  No data may be sent to a channel until a&lt;br /&gt;message is received to indicate that window space is available.&lt;br /&gt;&lt;br /&gt;3.1.  Opening a Channel&lt;br /&gt;&lt;br /&gt;When either side wishes to open a new channel, it allocates a local&lt;br /&gt;number for the channel.  It then sends the following message to the&lt;br /&gt;other side, and includes the local channel number and initial window&lt;br /&gt;size in the message.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN&lt;br /&gt;  string    channel type (restricted to US-ASCII)&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;  ... channel type specific data follows&lt;br /&gt;&lt;br /&gt;The channel type is a name as described in the SSH architecture&lt;br /&gt;document, with similar extension mechanisms. `sender channel' is a local&lt;br /&gt;identifier for the channel used by the sender of this message.  `initial&lt;br /&gt;window size' specifies how many bytes of channel data can be sent to the&lt;br /&gt;sender of this message without adjusting the window. `Maximum packet&lt;br /&gt;size' specifies the maximum size of an individual data packet that can&lt;br /&gt;be sent to the sender (for example, one might want to use smaller&lt;br /&gt;packets for interactive connections to get better interactive response&lt;br /&gt;on slow links).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 3]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;The remote side then decides whether it can open the channel, and&lt;br /&gt;responds with either&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN_CONFIRMATION&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;  ... channel type specific data follows&lt;br /&gt;&lt;br /&gt;where `recipient channel' is the channel number given in the original&lt;br /&gt;open request, and `sender channel' is the channel number allocated by&lt;br /&gt;the other side, or&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN_FAILURE&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  uint32    reason code&lt;br /&gt;  string    additional textual information (ISO-10646 UTF-8&lt;br /&gt;            [RFC-2044])&lt;br /&gt;  string    language tag (as defined in [RFC-1766])&lt;br /&gt;&lt;br /&gt;If the recipient of the SSH_MSG_CHANNEL_OPEN message does not support&lt;br /&gt;the specified channel type, it simply responds with&lt;br /&gt;SSH_MSG_CHANNEL_OPEN_FAILURE. The client MAY show the additional&lt;br /&gt;information to the user. If this is done, the client software should&lt;br /&gt;take the precautions discussed in [SSH-ARCH].&lt;br /&gt;&lt;br /&gt;The following reason codes are defined:&lt;br /&gt;&lt;br /&gt;#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED    1&lt;br /&gt;#define SSH_OPEN_CONNECT_FAILED                 2&lt;br /&gt;#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE           3&lt;br /&gt;#define SSH_OPEN_RESOURCE_SHORTAGE              4&lt;br /&gt;&lt;br /&gt;3.2.  Data Transfer&lt;br /&gt;&lt;br /&gt;The window size specifies how many bytes the other party can send before&lt;br /&gt;it must wait for the window to be adjusted.  Both parties use the&lt;br /&gt;following message to adjust the window.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_WINDOW_ADJUST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  uint32    bytes to add&lt;br /&gt;&lt;br /&gt;After receiving this message, the recipient MAY send the given number of&lt;br /&gt;bytes more than it was previously allowed to send; the window size is&lt;br /&gt;incremented.&lt;br /&gt;&lt;br /&gt;Data transfer is done with messages of the following type.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_DATA&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    data&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 4]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;The maximum amount of data allowed is the current window size.  The&lt;br /&gt;window size is decremented by the amount of data sent. Both parties MAY&lt;br /&gt;ignore all extra data sent after the allowed window is empty.&lt;br /&gt;&lt;br /&gt;Additionally, some channels can transfer several types of data.  An&lt;br /&gt;example of this is stderr data from interactive sessions.  Such data can&lt;br /&gt;be passed with SSH_MSG_CHANNEL_EXTENDED_DATA messages, where a separate&lt;br /&gt;integer specifies the type of the data.  The available types and their&lt;br /&gt;interpretation depend on the type of the channel.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_EXTENDED_DATA&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;  uint32    data_type_code&lt;br /&gt;  string    data&lt;br /&gt;&lt;br /&gt;Data sent with these messages consumes the same window as ordinary data.&lt;br /&gt;&lt;br /&gt;Currently, only the following type is defined.&lt;br /&gt;&lt;br /&gt;#define SSH_EXTENDED_DATA_STDERR                1&lt;br /&gt;&lt;br /&gt;3.3.  Closing a Channel&lt;br /&gt;&lt;br /&gt;When a party will no longer send more data to a channel, it SHOULD send&lt;br /&gt;SSH_MSG_CHANNEL_EOF.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_EOF&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;&lt;br /&gt;No explicit response is sent to this message; however, the application&lt;br /&gt;may send EOF to whatever is at the other end of the channel.  Note that&lt;br /&gt;the channel remains open after this message, and more data may still be&lt;br /&gt;sent in the other direction.  This message does not consume window space&lt;br /&gt;and can be sent even if no window space is available.&lt;br /&gt;&lt;br /&gt;When either party wishes to terminate the channel, it sends&lt;br /&gt;SSH_MSG_CHANNEL_CLOSE.  Upon receiving this message, a party MUST send&lt;br /&gt;back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this message for&lt;br /&gt;the channel.  The channel is considered closed for a party when it has&lt;br /&gt;both sent and received SSH_MSG_CHANNEL_CLOSE, and the party may then&lt;br /&gt;reuse the channel number.  A party MAY send SSH_MSG_CHANNEL_CLOSE&lt;br /&gt;without having sent or received SSH_MSG_CHANNEL_EOF.&lt;br /&gt;  byte      SSH_MSG_CHANNEL_CLOSE&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;&lt;br /&gt;This message does not consume window space and can be sent even if no&lt;br /&gt;window space is available.&lt;br /&gt;&lt;br /&gt;It is recommended that any data sent before this message is delivered to&lt;br /&gt;the actual destination, if possible.&lt;br /&gt;&lt;br /&gt;3.4.  Channel-Specific Requests&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 5]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;Many channel types have extensions that are specific to that particular&lt;br /&gt;channel type.  An example is requesting a pty (pseudo terminal) for an&lt;br /&gt;interactive session.&lt;br /&gt;&lt;br /&gt;All channel-specific requests use the following format.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    request type (restricted to US-ASCII)&lt;br /&gt;  boolean   want reply&lt;br /&gt;  ... type-specific data&lt;br /&gt;&lt;br /&gt;If want reply is FALSE, no response will be sent to the request.&lt;br /&gt;Otherwise, the recipient responds with either SSH_MSG_CHANNEL_SUCCESS or&lt;br /&gt;SSH_MSG_CHANNEL_FAILURE, or request-specific continuation messages.  If&lt;br /&gt;the request is not recognized or is not supported for the channel,&lt;br /&gt;SSH_MSG_CHANNEL_FAILURE is returned.&lt;br /&gt;&lt;br /&gt;This message does not consume window space and can be sent even if no&lt;br /&gt;window space is available. Request types are local to each channel type.&lt;br /&gt;&lt;br /&gt;The client is allowed to send further messages without waiting for the&lt;br /&gt;response to the request.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_SUCCESS&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_FAILURE&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;&lt;br /&gt;These messages do not consume window space and can be sent even if no&lt;br /&gt;window space is available.&lt;br /&gt;4.  Interactive Sessions&lt;br /&gt;&lt;br /&gt;A session is a remote execution of a program.  The program may be a&lt;br /&gt;shell, an application, a system command, or some built-in subsystem.  It&lt;br /&gt;may or may not have a tty, and may or may not involve X11 forwarding.&lt;br /&gt;Multiple sessions can be active simultaneously.&lt;br /&gt;&lt;br /&gt;4.1.  Opening a Session&lt;br /&gt;&lt;br /&gt;A session is started by sending the following message.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN&lt;br /&gt;  string    "session"&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;&lt;br /&gt;Client implementations SHOULD reject any session channel open requests&lt;br /&gt;to make it more difficult for a corrupt server to attack the client.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 6]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;4.2.  Requesting a Pseudo-Terminal&lt;br /&gt;&lt;br /&gt;A pseudo-terminal can be allocated for the session by sending the&lt;br /&gt;following message.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;  string    "pty-req"&lt;br /&gt;  boolean   want_reply&lt;br /&gt;  string    TERM environment variable value (e.g., vt100)&lt;br /&gt;  uint32    terminal width, characters (e.g., 80)&lt;br /&gt;  uint32    terminal height, rows (e.g., 24)&lt;br /&gt;  uint32    terminal width, pixels (e.g., 480)&lt;br /&gt;  uint32    terminal height, pixels (e.g., 640)&lt;br /&gt;  string    encoded terminal modes&lt;br /&gt;&lt;br /&gt;The encoding of terminal modes is described in Section ``Encoding of&lt;br /&gt;Terminal Modes''. Zero dimension parameters MUST be ignored. The&lt;br /&gt;character/row dimensions override the pixel dimensions (when nonzero).&lt;br /&gt;Pixel dimensions refer to the drawable area of the window.&lt;br /&gt;&lt;br /&gt;The dimension parameters are only informational.&lt;br /&gt;&lt;br /&gt;The client SHOULD ignore pty requests.&lt;br /&gt;&lt;br /&gt;4.3.  X11 Forwarding&lt;br /&gt;&lt;br /&gt;4.3.1.  Requesting X11 Forwarding&lt;br /&gt;&lt;br /&gt;X11 forwarding may be requested for a session by sending&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "x11-req"&lt;br /&gt;  boolean   want reply&lt;br /&gt;  boolean   single connection&lt;br /&gt;  string    x11 authentication protocol&lt;br /&gt;  string    x11 authentication cookie&lt;br /&gt;  uint32    x11 screen number&lt;br /&gt;&lt;br /&gt;It is recommended that the authentication cookie that is sent be a fake,&lt;br /&gt;random cookie, and that the cookie is checked and replaced by the real&lt;br /&gt;cookie when a connection request is received.&lt;br /&gt;&lt;br /&gt;X11 connection forwarding should stop when the session channel is&lt;br /&gt;closed; however, already opened forwardings should not be automatically&lt;br /&gt;closed when the session channel is closed.&lt;br /&gt;&lt;br /&gt;If `single connection' is TRUE, only a single connection should be&lt;br /&gt;forwarded.  No more connections will be forwarded after the first, or&lt;br /&gt;after the session channel has been closed.&lt;br /&gt;&lt;br /&gt;`X11 authentication protocol is the name of the X11 authentication&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 7]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;method used, i.e. "MIT-MAGIC-COOKIE-1".&lt;br /&gt;&lt;br /&gt;X Protocol is documented in [Scheifler].&lt;br /&gt;&lt;br /&gt;4.3.2.  X11 Channels&lt;br /&gt;&lt;br /&gt;X11 channels are opened with a channel open request.  The resulting&lt;br /&gt;channels are independent of the session, and closing the session channel&lt;br /&gt;does not close the forwarded X11 channels.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN&lt;br /&gt;  string    "x11"&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;  string    originator address (e.g. "192.168.7.38")&lt;br /&gt;  uint32    originator port&lt;br /&gt;&lt;br /&gt;The recipient should respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION or&lt;br /&gt;SSH_MSG_CHANNEL_OPEN_FAILURE.&lt;br /&gt;&lt;br /&gt;Implementations MUST reject any X11 channel open requests if they have&lt;br /&gt;not requested X11 forwarding.&lt;br /&gt;&lt;br /&gt;4.4.  Environment Variable Passing&lt;br /&gt;&lt;br /&gt;Environment variables may be passed to the shell/command to be started&lt;br /&gt;later.  Typically, each machine will have a preconfigured set of&lt;br /&gt;variables that it will allow.  Since uncontrolled setting of environment&lt;br /&gt;variables can be very dangerous, it is recommended that implementations&lt;br /&gt;allow setting only variables whose names have been explicitly configured&lt;br /&gt;to be allowed.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "env"&lt;br /&gt;  boolean   want reply&lt;br /&gt;  string    variable name&lt;br /&gt;  string    variable value&lt;br /&gt;&lt;br /&gt;4.5.  Starting a Shell or a Command&lt;br /&gt;&lt;br /&gt;Once the session has been set up, a program is started at the remote&lt;br /&gt;end. The program can be a shell, an application program or a subsystem&lt;br /&gt;with a host-independent name.  Only one of these requests can succeed&lt;br /&gt;per channel.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "shell"&lt;br /&gt;  boolean   want reply&lt;br /&gt;&lt;br /&gt;This message will request the user's default shell (typically defined in&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 8]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;/etc/passwd in UNIX systems) to be started at the other end.&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "exec"&lt;br /&gt;  boolean   want reply&lt;br /&gt;  string    command&lt;br /&gt;&lt;br /&gt;This message will request the server to start the execution of the given&lt;br /&gt;command. The command string may contain a path. Normal precautions MUST&lt;br /&gt;be taken to prevent the execution of unauthorized commands.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "subsystem"&lt;br /&gt;  boolean   want reply&lt;br /&gt;  string    subsystem name&lt;br /&gt;&lt;br /&gt;This last form executes a predefined subsystem.  It expected that these&lt;br /&gt;will include a general file transfer mechanism, and possibly other&lt;br /&gt;features.  Implementations may also allow configuring more such&lt;br /&gt;mechanisms.&lt;br /&gt;&lt;br /&gt;The server SHOULD not halt the execution of the protocol stack when&lt;br /&gt;starting a shell or a program. All input and output from these SHOULD be&lt;br /&gt;redirected to the channel or to the encrypted tunnel.&lt;br /&gt;&lt;br /&gt;It is RECOMMENDED to request and check the reply for these messages. The&lt;br /&gt;client SHOULD ignore these messages.&lt;br /&gt;&lt;br /&gt;4.6.  Session Data Transfer&lt;br /&gt;&lt;br /&gt;Data transfer for a session is done using SSH_MSG_CHANNEL_DATA and&lt;br /&gt;SSH_MSG_CHANNEL_EXTENDED_DATA packets and the window mechanism.  The&lt;br /&gt;extended data type SSH_EXTENDED_DATA_STDERR has been defined for stderr&lt;br /&gt;data.&lt;br /&gt;&lt;br /&gt;4.7.  Window Dimension Change Message&lt;br /&gt;&lt;br /&gt;When the window (terminal) size changes on the client side, it MAY send&lt;br /&gt;a message to the other side to inform it of the new dimensions.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;  string    "window-change"&lt;br /&gt;  boolean   FALSE&lt;br /&gt;  uint32    terminal width, columns&lt;br /&gt;  uint32    terminal height, rows&lt;br /&gt;  uint32    terminal width, pixels&lt;br /&gt;  uint32    terminal height, pixels&lt;br /&gt;&lt;br /&gt;No response SHOULD be sent to this message.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen    [page 9]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;4.8.  Local Flow Control&lt;br /&gt;&lt;br /&gt;On many systems, it is possible to determine if a pseudo-terminal is&lt;br /&gt;using control-S/control-Q flow control.  When flow control is allowed,&lt;br /&gt;it is often desirable to do the flow control at the client end to speed&lt;br /&gt;up responses to user requests.  This is facilitated by the following&lt;br /&gt;notification.  Initially, the server is responsible for flow control.&lt;br /&gt;(Here, again, client means the side originating the session, and server&lt;br /&gt;means the other side.)&lt;br /&gt;&lt;br /&gt;The message below is used by the server to inform the client when it can&lt;br /&gt;or cannot perform flow control (control-S/control-Q processing).  If&lt;br /&gt;`client can do' is TRUE, the client is allowed to do flow control using&lt;br /&gt;control-S and control-Q.  The client MAY ignore this message.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "xon-xoff"&lt;br /&gt;  boolean   FALSE&lt;br /&gt;  boolean   client can do&lt;br /&gt;&lt;br /&gt;No response is sent to this message.&lt;br /&gt;&lt;br /&gt;4.9.  Signals&lt;br /&gt;&lt;br /&gt;A signal can be delivered to the remote process/service using the&lt;br /&gt;following message.  Some systems may not implement signals, in which&lt;br /&gt;case they SHOULD ignore this message.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "signal"&lt;br /&gt;  boolean   FALSE&lt;br /&gt;  string    signal name without the "SIG" prefix.&lt;br /&gt;&lt;br /&gt;Signal names will be encoded as discussed in the "exit-signal"&lt;br /&gt;SSH_MSG_CHANNEL_REQUEST.&lt;br /&gt;&lt;br /&gt;4.10.  Returning Exit Status&lt;br /&gt;&lt;br /&gt;When the command running at the other end terminates, the following&lt;br /&gt;message can be sent to return the exit status of the command.  Returning&lt;br /&gt;the status is RECOMMENDED.  No acknowledgment is sent for this message.&lt;br /&gt;The channel needs to be closed with SSH_MSG_CHANNEL_CLOSE after this&lt;br /&gt;message.&lt;br /&gt;&lt;br /&gt;The client MAY ignore these messages.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient_channel&lt;br /&gt;  string    "exit-status"&lt;br /&gt;  boolean   FALSE&lt;br /&gt;  uint32    exit_status&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 10]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;The remote command may also terminate violently due to a signal.  Such a&lt;br /&gt;condition can be indicated by the following message. A zero exit_status&lt;br /&gt;usually means that the command terminated successfully.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_REQUEST&lt;br /&gt;  uint32    recipient channel&lt;br /&gt;  string    "exit-signal"&lt;br /&gt;  boolean   FALSE&lt;br /&gt;  string    signal name without the "SIG" prefix.&lt;br /&gt;  boolean   core dumped&lt;br /&gt;  string    error message (ISO-10646 UTF-8 [RFC-2044])&lt;br /&gt;  string    language tag (as defined in [RFC-1766])&lt;br /&gt;&lt;br /&gt;The signal name is one of the following (these are from [POSIX]):&lt;br /&gt;&lt;br /&gt;  ABRT&lt;br /&gt;  ALRM&lt;br /&gt;  FPE&lt;br /&gt;  HUP&lt;br /&gt;  ILL&lt;br /&gt;  INT&lt;br /&gt;  KILL&lt;br /&gt;  PIPE&lt;br /&gt;  QUIT&lt;br /&gt;  SEGV&lt;br /&gt;  TERM&lt;br /&gt;  USR1&lt;br /&gt;  USR2&lt;br /&gt;&lt;br /&gt;Additional signal names MAY be sent in the format "sig-name@xyz", where&lt;br /&gt;`sig-name' and `xyz' may be anything a particular implementor wants&lt;br /&gt;(except the `@' sign). However, it is suggested that if a `configure'&lt;br /&gt;script is used, the non-standard signal names it finds be encoded as&lt;br /&gt;"SIG@xyz.config.guess", where `SIG' is the signal name without the "SIG"&lt;br /&gt;prefix, and `xyz' be the host type, as determined by `config.guess'.&lt;br /&gt;&lt;br /&gt;The `error message' contains an additional explanation of the error&lt;br /&gt;message. The message may consist of multiple lines. The client software&lt;br /&gt;MAY display this message to the user. If this is done, the client&lt;br /&gt;software should take the precautions discussed in [SSH-ARCH].&lt;br /&gt;&lt;br /&gt;5.  TCP/IP Port Forwarding&lt;br /&gt;&lt;br /&gt;5.1.  Requesting Port Forwarding&lt;br /&gt;&lt;br /&gt;A party need not explicitly request forwardings from its own end to the&lt;br /&gt;other direction.  However, if it wishes that connections to a port on&lt;br /&gt;the other side be forwarded to the local side, it must explicitly&lt;br /&gt;request this.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_GLOBAL_REQUEST&lt;br /&gt;  string    "tcpip-forward"&lt;br /&gt;  boolean   want reply&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 11]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;  string    address to bind (e.g. "0.0.0.0")&lt;br /&gt;  uint32    port number to bind&lt;br /&gt;&lt;br /&gt;`Address to bind' and `port number to bind' specify the IP address and&lt;br /&gt;port to which the socket to be listened is bound.  The address should be&lt;br /&gt;"0.0.0.0" if connections are allowed from anywhere.  (Note that the&lt;br /&gt;client can still filter connections based on information passed in the&lt;br /&gt;open request.)&lt;br /&gt;&lt;br /&gt;Implementations should only allow forwarding privileged ports if the&lt;br /&gt;user has been authenticated as a privileged user.&lt;br /&gt;&lt;br /&gt;Client implementations SHOULD reject these messages; they are normally&lt;br /&gt;only sent by the client.&lt;br /&gt;&lt;br /&gt;A port forwarding can be cancelled with the following message.  Note&lt;br /&gt;that channel open requests may be received until a reply to this message&lt;br /&gt;is received.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_GLOBAL_REQUEST&lt;br /&gt;  string    "cancel-tcpip-forward"&lt;br /&gt;  boolean   want reply&lt;br /&gt;  string    address_to_bind (e.g. "127.0.0.1")&lt;br /&gt;  uint32    port number to bind&lt;br /&gt;&lt;br /&gt;Client implementations SHOULD reject these messages; they are normally&lt;br /&gt;only sent by the client.&lt;br /&gt;&lt;br /&gt;5.2.  TCP/IP Forwarding Channels&lt;br /&gt;&lt;br /&gt;When a connection comes to a port for which remote forwarding has been&lt;br /&gt;requested, a channel is opened to forward the port to the other side.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN&lt;br /&gt;  string    "forwarded-tcpip"&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;  string    address that was connected&lt;br /&gt;  uint32    port that was connected&lt;br /&gt;  string    originator IP address&lt;br /&gt;  uint32    originator port&lt;br /&gt;&lt;br /&gt;Implementations MUST reject these messages unless they have previously&lt;br /&gt;requested a remote TCP/IP port forwarding with the given port number.&lt;br /&gt;&lt;br /&gt;When a connection comes to a locally forwarded TCP/IP port, the&lt;br /&gt;following packet is sent to the other side.  Note that these messages&lt;br /&gt;MAY be sent also for ports for which no forwarding has been explicitly&lt;br /&gt;requested.  The receiving side must decide whether to allow the&lt;br /&gt;forwarding.&lt;br /&gt;&lt;br /&gt;  byte      SSH_MSG_CHANNEL_OPEN&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 12]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;  string    "direct-tcpip"&lt;br /&gt;  uint32    sender channel&lt;br /&gt;  uint32    initial window size&lt;br /&gt;  uint32    maximum packet size&lt;br /&gt;  string    host to connect&lt;br /&gt;  uint32    port to connect&lt;br /&gt;  string    originator IP address&lt;br /&gt;  uint32    originator port&lt;br /&gt;&lt;br /&gt;`Host to connect' and `port to connect' specify the TCP/IP host and port&lt;br /&gt;where the recipient should connect the channel.  `Host to connect' may&lt;br /&gt;be either a domain name or a numeric IP address.&lt;br /&gt;&lt;br /&gt;`Originator IP address' is the numeric IP address of the machine where&lt;br /&gt;the connection request comes from, and `originator port' is the port on&lt;br /&gt;the originator host from where the connection came from.&lt;br /&gt;&lt;br /&gt;Forwarded TCP/IP channels are independent of any sessions, and closing a&lt;br /&gt;session channel does not in any way imply that forwarded connections&lt;br /&gt;should be closed.&lt;br /&gt;&lt;br /&gt;Client implementations SHOULD reject direct TCP/IP open requests for&lt;br /&gt;security reasons.&lt;br /&gt;&lt;br /&gt;6.  Encoding of Terminal Modes&lt;br /&gt;&lt;br /&gt;Terminal modes (as passed in a pty request) are encoded into a byte&lt;br /&gt;stream.  It is intended that the coding be portable across different&lt;br /&gt;environments.&lt;br /&gt;&lt;br /&gt;The tty mode description is a stream of bytes.  The stream consists of&lt;br /&gt;opcode-argument pairs.  It is terminated by opcode TTY_OP_END (0).&lt;br /&gt;Opcodes 1 to 159 have a single uint32 argument. Opcodes 160 to 255 are&lt;br /&gt;not yet defined, and cause parsing to stop (they should only be used&lt;br /&gt;after any other data).&lt;br /&gt;&lt;br /&gt;The client SHOULD put in the stream any modes it knows about, and the&lt;br /&gt;server MAY ignore any modes it does not know about.  This allows some&lt;br /&gt;degree of machine-independence, at least between systems that use a&lt;br /&gt;POSIX-like tty interface.  The protocol can support other systems as&lt;br /&gt;well, but the client may need to fill reasonable values for a number of&lt;br /&gt;parameters so the server pty gets set to a reasonable mode (the server&lt;br /&gt;leaves all unspecified mode bits in their default values, and only some&lt;br /&gt;combinations make sense).&lt;br /&gt;&lt;br /&gt;The following opcodes have been defined.  The naming of opcodes mostly&lt;br /&gt;follows the POSIX terminal mode flags.&lt;br /&gt;&lt;br /&gt;0   TTY_OP_END     Indicates end of options.&lt;br /&gt;1   VINTR          Interrupt character; 255 if none.  Similarly for the&lt;br /&gt;                   other characters. Not all of these characters are&lt;br /&gt;                   supported on all systems.&lt;br /&gt;2   VQUIT          The quit character (sends SIGQUIT signal on POSIX&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 13]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;                   systems).&lt;br /&gt;3   VERASE         Erase the character to left of the cursor.&lt;br /&gt;4   VKILL          Kill the current input line.&lt;br /&gt;5   VEOF           End-of-file character (sends EOF from the terminal).&lt;br /&gt;6   VEOL           End-of-line character in addition to carriage return&lt;br /&gt;                   and/or linefeed.&lt;br /&gt;7   VEOL2          Additional end-of-line character.&lt;br /&gt;8   VSTART         Continues paused output (normally control-Q).&lt;br /&gt;9   VSTOP          Pauses output (normally control-S).&lt;br /&gt;10  VSUSP          Suspends the current program.&lt;br /&gt;11  VDSUSP         Another suspend character.&lt;br /&gt;12  VREPRINT       Reprints the current input line.&lt;br /&gt;13  VWERASE        Erases a word left of cursor.&lt;br /&gt;14  VLNEXT         Enter the next character typed literally, even if it&lt;br /&gt;                   is a special character&lt;br /&gt;15  VFLUSH         Character to flush output.&lt;br /&gt;16  VSWTCH         Switch to a different shell layer.&lt;br /&gt;17  VSTATUS        Prints system status line (load, command, pid etc).&lt;br /&gt;18  VDISCARD       Toggles the flushing of terminal output.&lt;br /&gt;30  IGNPAR         The ignore parity flag.  The parameter SHOULD be 0 if&lt;br /&gt;                   this flag is FALSE set, and 1 if it is TRUE.&lt;br /&gt;31  PARMRK         Mark parity and framing errors.&lt;br /&gt;32  INPCK          Enable checking of parity errors.&lt;br /&gt;33  ISTRIP         Strip 8th bit off characters.&lt;br /&gt;34  INLCR          Map NL into CR on input.&lt;br /&gt;35  IGNCR          Ignore CR on input.&lt;br /&gt;36  ICRNL          Map CR to NL on input.&lt;br /&gt;37  IUCLC          Translate uppercase characters to lowercase.&lt;br /&gt;38  IXON           Enable output flow control.&lt;br /&gt;39  IXANY          Any char will restart after stop.&lt;br /&gt;40  IXOFF          Enable input flow control.&lt;br /&gt;41  IMAXBEL        Ring bell on input queue full.&lt;br /&gt;50  ISIG           Enable signals INTR, QUIT, [D]SUSP.&lt;br /&gt;51  ICANON         Canonicalize input lines.&lt;br /&gt;52  XCASE          Enable input and output of uppercase characters by&lt;br /&gt;                   preceding their lowercase equivalents with `\'.&lt;br /&gt;53  ECHO           Enable echoing.&lt;br /&gt;54  ECHOE          Visually erase chars.&lt;br /&gt;55  ECHOK          Kill character discards current line.&lt;br /&gt;56  ECHONL         Echo NL even if ECHO is off.&lt;br /&gt;57  NOFLSH         Don't flush after interrupt.&lt;br /&gt;58  TOSTOP         Stop background jobs from output.&lt;br /&gt;59  IEXTEN         Enable extensions.&lt;br /&gt;60  ECHOCTL        Echo control characters as ^(Char).&lt;br /&gt;61  ECHOKE         Visual erase for line kill.&lt;br /&gt;62  PENDIN         Retype pending input.&lt;br /&gt;70  OPOST          Enable output processing.&lt;br /&gt;71  OLCUC          Convert lowercase to uppercase.&lt;br /&gt;72  ONLCR          Map NL to CR-NL.&lt;br /&gt;73  OCRNL          Translate carriage return to newline (output).&lt;br /&gt;74  ONOCR          Translate newline to carriage return-newline&lt;br /&gt;                   (output).&lt;br /&gt;75  ONLRET         Newline performs a carriage return (output).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 14]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;90  CS7            7 bit mode.&lt;br /&gt;91  CS8            8 bit mode.&lt;br /&gt;92  PARENB         Parity enable.&lt;br /&gt;93  PARODD         Odd parity, else even.&lt;br /&gt;&lt;br /&gt;128 TTY_OP_ISPEED  Specifies the input baud rate in bits per second.&lt;br /&gt;129 TTY_OP_OSPEED  Specifies the output baud rate in bits per second.&lt;br /&gt;&lt;br /&gt;7.  Summary of Message Numbers&lt;br /&gt;&lt;br /&gt;  #define SSH_MSG_GLOBAL_REQUEST                  80&lt;br /&gt;  #define SSH_MSG_REQUEST_SUCCESS                 81&lt;br /&gt;  #define SSH_MSG_REQUEST_FAILURE                 82&lt;br /&gt;  #define SSH_MSG_CHANNEL_OPEN                    90&lt;br /&gt;  #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION       91&lt;br /&gt;  #define SSH_MSG_CHANNEL_OPEN_FAILURE            92&lt;br /&gt;  #define SSH_MSG_CHANNEL_WINDOW_ADJUST           93&lt;br /&gt;  #define SSH_MSG_CHANNEL_DATA                    94&lt;br /&gt;  #define SSH_MSG_CHANNEL_EXTENDED_DATA           95&lt;br /&gt;  #define SSH_MSG_CHANNEL_EOF                     96&lt;br /&gt;  #define SSH_MSG_CHANNEL_CLOSE                   97&lt;br /&gt;  #define SSH_MSG_CHANNEL_REQUEST                 98&lt;br /&gt;  #define SSH_MSG_CHANNEL_SUCCESS                 99&lt;br /&gt;  #define SSH_MSG_CHANNEL_FAILURE                 100&lt;br /&gt;&lt;br /&gt;8.  Security Considerations&lt;br /&gt;&lt;br /&gt;This protocol is assumed to run on top of a secure, authenticated&lt;br /&gt;transport.  User authentication and protection against network-level&lt;br /&gt;attacks are assumed to be provided by the underlying protocols.&lt;br /&gt;&lt;br /&gt;This protocol can, however, be used to execute commands on remote&lt;br /&gt;machines.  The protocol also permits the server to run commands on the&lt;br /&gt;client.  Implementations may wish to disallow this to prevent an&lt;br /&gt;attacker from coming from the server machine to the client machine.&lt;br /&gt;&lt;br /&gt;X11 forwarding provides major security improvements over normal cookie-&lt;br /&gt;based X11 forwarding.  The cookie never needs to be transmitted in the&lt;br /&gt;clear, and traffic is encrypted and integrity-protected.  No useful&lt;br /&gt;authentication data will remain on the server machine after the&lt;br /&gt;connection has been closed.  On the other hand, in some situations a&lt;br /&gt;forwarded X11 connection might be used to get access to the local X&lt;br /&gt;server across security perimeters.&lt;br /&gt;&lt;br /&gt;Port forwardings can potentially allow an intruder to cross security&lt;br /&gt;perimeters such as firewalls.  They do not offer anything fundamentally&lt;br /&gt;new that a user could not do otherwise; however, they make opening&lt;br /&gt;tunnels very easy.  Implementations should allow policy control over&lt;br /&gt;what can be forwarded.  Administrators should be able to deny&lt;br /&gt;forwardings where appropriate.&lt;br /&gt;&lt;br /&gt;Since this protocol normally runs inside an encrypted tunnel, firewalls&lt;br /&gt;will not be able to examine the traffic.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne and S. Lehtinen   [page 15]&lt;br /&gt;&lt;br /&gt;INTERNET-DRAFT                                              21 Nov, 2000&lt;br /&gt; &lt;br /&gt;It is RECOMMENDED that implementations disable all the potentially&lt;br /&gt;dangerous features (e.g. agent forwarding, X11 forwarding, and TCP/IP&lt;br /&gt;forwarding) if the host key has changed.&lt;br /&gt;&lt;br /&gt;9.  Trademark Issues&lt;br /&gt;&lt;br /&gt;SSH is a registered trademark and Secure Shell is a trademark of SSH&lt;br /&gt;Communications Security Corp.  SSH Communications Security Corp permits&lt;br /&gt;the use of these trademarks as the name of this standard and protocol,&lt;br /&gt;and permits their use to describe that a product conforms to this&lt;br /&gt;standard, provided that the following acknowledgement is included where&lt;br /&gt;the trademarks are used: ``SSH is a registered trademark and Secure&lt;br /&gt;Shell is a trademark of SSH Communications Security Corp&lt;br /&gt;(www.ssh.com)''.  These trademarks may not be used as part of a product&lt;br /&gt;name or in otherwise confusing manner without prior written permission&lt;br /&gt;of SSH Communications Security Corp&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-8811761996009683168?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/8811761996009683168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=8811761996009683168' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8811761996009683168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8811761996009683168'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/07/ssh-connection-protocol.html' title='SSH Connection Protocol'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-5976188275431572415</id><published>2008-07-23T21:38:00.000-07:00</published><updated>2008-07-23T21:42:46.811-07:00</updated><title type='text'>port setting from linux journel</title><content type='html'>&lt;p&gt;The Pro-Lite Tru-Color II PL-M2014R is an affordable multi-color LED scrolling message board that is capable of being controlled by a standard RS-232 serial port. The sign is obtainable from Pro-Lite directly (http://www.pro-lite.com/), but can also be purchased at various discount warehouses for approximately $150. The serial cable and Windows software are sold separately. &lt;/p&gt;&lt;p&gt;This article is not just a review; it can serve as a primer for Pro-Lite's PL-M2014R with ROM release 5.24Q and 32K of memory with Trivia mode, basically your standard sign. Until now, not much developer information has been available to the public, meaning signs were usually configured with the included infrared remote control to display static messages. For very little money, it is possible to build your own serial cable and control the sign using Linux to display more than static text.&lt;/p&gt;&lt;p&gt;The business and personal applications for a highly visible sign are almost limitless: reporting days until software delivery, announcing traffic congestion, providing the weather, showing the date and time, sending public messages, reporting system load, announcing new mail, showing who's logged in, warning when disk space gets low, login information, announcing unexpected server outages as a watchdog, etc.&lt;/p&gt;&lt;p&gt;Communicating with the sign is almost as simple as beaming text out the serial port; however, a bit of text manipulation is necessary in order to get the sign to respond and do advanced tasks. Linux handles the serial port communication, so sending information to the sign appears as trivial as writing to a file.&lt;/p&gt;&lt;p&gt;Luckily, the majority of the work can be accomplished by simple scripts. All you need is a basic understanding of the shell, AWK, PERL or Python, and you can be running in almost no time. The first hurdle is to build a cable and configure Linux to talk out the serial port.&lt;/p&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb45460"&gt;&lt;/a&gt;Cable Construction&lt;/div&gt;&lt;div class="mediaobject"&gt;&lt;img src="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f2.png" /&gt;&lt;div class="caption"&gt;&lt;p&gt; Figure 1. Female DB9 Adapter &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The first step is wiring an RJ12 to female DB9 adapter. It requires no tools, and an adapter kit can be purchased at most computer supply stores for about $2 US. The only other thing you need is a length of RJ12 cable with male adapters at each end. This means a standard telephone cord will do nicely. Your cable will most likely have the standard colors black, red, green and yellow, in that order.&lt;/p&gt;&lt;p&gt;Cables come in two flavors: straight-thru and reversed. You'll need to take the RJ12 cable and put it end to end (like a loop) to find out which kind of adapter you need to build.&lt;/p&gt;&lt;div class="mediaobject"&gt;&lt;img src="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f3.png" /&gt;&lt;div class="caption"&gt;&lt;p&gt; Figure 2. RJ12 Adapter Diagram &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;One of two things will be noticeable: either the wires will match black to black, red to red and so on, or they will reverse their order showing black to yellow, red to green and so on.&lt;/p&gt;&lt;p&gt;If the cable is a straight-through, where the colors match, wire your RJ12 to a DB9 adapter using Pin 2 as green, Pin 3 as red and Pin 5 as yellow. If the cable is reversed, then where the colors reverse sequence, wire your RJ12 to a DB9 adapter using Pin 2 as red, Pin 3 as green and Pin 5 as black.&lt;/p&gt;&lt;div class="mediaobject"&gt;&lt;a href="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f5.png"&gt;&lt;img src="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f5.inline.png" /&gt;&lt;/a&gt;&lt;div class="caption"&gt;&lt;p&gt; Figure 3. RJ12 to DB9 Wiring &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Shove the unused adapter wires into the casing and snap the adapter shut. Take care not to let the exposed ends touch anything metal inside the adapter casing. You may want to clip the unused wires. Put an extension cable on your serial port and connect the adapter wires directly to the extension cable in order to test the wiring configuration before pushing the pins into the connector.&lt;/p&gt;&lt;p&gt;When all is said and done, one end of the RJ12 goes into the side of the LED sign, the other into the adapter you just made, and the adapter plugs into the computer.&lt;/p&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb45c48"&gt;&lt;/a&gt;Configuring Linux to Talk to the Sign&lt;/div&gt;&lt;p&gt;My sign is plugged into COM1, also known as /dev/ttyS0. I've elected to use a symbolic link to the sign, in the event I ever decide to change to another serial port in the future. To make the link, as root type:&lt;/p&gt;&lt;pre class="programlisting"&gt;ln -s /dev/ttyS0 /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I tend to shy away from doing development as root. Putting security issues aside for the moment, we can make the device world-writable by typing: &lt;/p&gt;&lt;pre class="programlisting"&gt;chmod a+rw /dev/prolite&lt;br /&gt;&lt;/pre&gt;   The sign communicates using No Parity, 8 Bits, 1 Stop Bit; no handshaking of any kind (hardware or software) is used. Early versions of the sign work only at 300 baud, but they can be upgraded to 9600 baud. All signs I've encountered had the 9600 capability right out of the box. The bottom line is that all signs are capable of communication, and even at 300 baud you can outrun the sign. The only drawback is that the sign's baud rate has to be set by the remote control, according to the setup in the manual. This needs to be done only once. &lt;p&gt;In theory, the sign requires a 15ms delay between each character sent to the sign. I've found that Linux's device driver seems to work just fine without having to do anything special in the software.&lt;/p&gt;&lt;pre class="programlisting"&gt;stty speed 9600 cs8 -parenb -cstopb cread \&lt;br /&gt;  -clocal -crtscts -ignpar -echo nl1 cr3 &lt; \&lt;br /&gt;  /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Naturally, you can substitute any baud rate the sign will handle for the 9600. This command will work when you aren't root because it is world-writable. &lt;/p&gt;&lt;p&gt;The most important piece of information for communicating with the sign is that each command sent to the sign must end with a carriage return/newline pair. This is &lt;b&gt;ctrl-M ctrl-J&lt;/b&gt; on the keyboard or 0x0C 0x0A in hexadecimal. C programmers will recognize it as \r\n. If you want Linux to handle the end-of-line sequence for you, type the command:&lt;/p&gt;&lt;pre class="programlisting"&gt;stty opost -ocrnl onlcr &lt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;When you send a newline, Linux will send both carriage return/newline automatically. Text can now be listed or redirected to /dev/prolite from the shell. If you want to send the carriage returns yourself, type: &lt;/p&gt;&lt;pre class="programlisting"&gt;stty -opost -ocrnl -onlcr &lt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;   Where the options are defined as: &lt;div class="itemizedlist"&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;opost&lt;/b&gt;: postprocess the output stream.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;-opost&lt;/b&gt;: do not postprocess the output stream.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;-ocrnl&lt;/b&gt;: do not convert carriage returns into newlines.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;-onlcr&lt;/b&gt;: do not translate each newline into a carriage return/newline pair.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;b&gt;onlcr&lt;/b&gt;: translate each newline into a carriage return/newline pair.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;  The &lt;span class="bold"&gt;&lt;b&gt;stty&lt;/b&gt;&lt;/span&gt; command allows for a shorthand representation of all the termios structures that define the device characteristics. For 9600,N,8,1 with automatic carriage returns, type on one line: &lt;pre class="programlisting"&gt;stty 0:705:bd:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:&lt;br /&gt;12:f:17:16:0:0:73 &lt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;   For 9600,N,8,1 with no automatic carriage returns, use the line: &lt;pre class="programlisting"&gt;stty 0:700:bd:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:&lt;br /&gt;12:f:17:16:0:0:73 &lt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;   &lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb3d0f0"&gt;&lt;/a&gt;Command Syntax&lt;/div&gt;&lt;p&gt;Only a minimal understanding is needed in order to operate the sign. Mastery requires becoming familiar with the protocol and doing a little experimenting.&lt;/p&gt;&lt;p&gt;Multiple signs can be connected to a computer over the same serial port by using a simple telephone-line-splitting Y-connector. Each sign has an assignable logical address that allows you to send messages to particular signs. A logical address is represented in hexadecimal as a number between 01 and FF. Addresses may be shared enabling grouping; in this way, a message to ID01 goes to all signs with ID01.&lt;/p&gt;&lt;p&gt;Communication with the sign is always done with readable ASCII characters; thus, an arbitrary ID of 2F would be designated with the digit “2” and the capital letter “F”.&lt;/p&gt;&lt;p&gt;ID00 is reserved to mean “broadcast to all signs”. By default, a sign is preconfigured as ID01; this can be changed with the remote control. If you are addressing a single sign connected straight to the computer, it will respond with its ID number after each successful command. Messages sent to ID00 do not return a response, and neither does an individual sign when the line is shared via the Y-connector.&lt;/p&gt;&lt;p&gt;All messages to the sign, except for those setting the date and time, are sent in the following format followed by the carriage return/line feed: &lt;b&gt;&lt;id&lt;i&gt;&lt;tt&gt;xx&lt;/tt&gt;&lt;/i&gt;&gt;&lt;i&gt;&lt;tt&gt;command&lt;/tt&gt;&lt;/i&gt;&lt;/b&gt;, &lt;span class="emphasis"&gt;&lt;em&gt;xx&lt;/em&gt;&lt;/span&gt; is 00 to FF. Any command longer than 1,023 bytes will be ignored by the sign.&lt;/p&gt;&lt;p&gt;To set the date and time, no ID is needed. The format is &lt;b&gt;&lt;&lt;i&gt;&lt;tt&gt;TYYMMDDwhhmmss&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt; where &lt;span class="emphasis"&gt;&lt;em&gt;YY&lt;/em&gt;&lt;/span&gt; is the year, &lt;span class="emphasis"&gt;&lt;em&gt;MM&lt;/em&gt;&lt;/span&gt; the month, &lt;span class="emphasis"&gt;&lt;em&gt;DD&lt;/em&gt;&lt;/span&gt; the day, &lt;span class="emphasis"&gt;&lt;em&gt;w&lt;/em&gt;&lt;/span&gt; the weekday (0=Sun, 1=Mon,...6=Sat), &lt;span class="emphasis"&gt;&lt;em&gt;hh&lt;/em&gt;&lt;/span&gt; the hour, &lt;span class="emphasis"&gt;&lt;em&gt;mm&lt;/em&gt;&lt;/span&gt; the minute and &lt;span class="emphasis"&gt;&lt;em&gt;ss&lt;/em&gt;&lt;/span&gt; the seconds. This can be accomplished with the shell very easily. Set the date/time of all signs with the command:&lt;/p&gt;&lt;pre class="programlisting"&gt;ate "+&lt;t%y%m%d%w%h%m%s&gt;" te "+&lt;t%y%m%d%w%h%m%s&gt;" &gt; /dev/prolite&gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The leading &lt;b&gt;+&lt;/b&gt; sign tells the date command to build a string via substitution; see your man pages for details. &lt;/p&gt;&lt;p&gt;To signal a sign to start listening to responses, send it an empty command with the format &lt;b&gt;&lt;id&lt;i&gt;&lt;tt&gt;xx&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;; e.g., type:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb3da90"&gt;&lt;/a&gt;Pages&lt;/div&gt;&lt;p&gt;The most fundamental concept of the sign is the idea of a page. A page consists of a message the sign is to display either now or some time in the future. Pages may contain text, numerics, symbols, font attribute tags, color tags, graphic tags and effect tags. There are 26 pages named, appropriately enough, A to Z. Case does matter when identifying a page.&lt;/p&gt;&lt;p&gt;Any given page can hold approximately 1,012 bytes of information. I say approximately because special tags (see sidebar) consume more than one byte, which means less space. Also, using some trickery by omitting the page directive completely and defaulting to page A squeezes out an additional two bytes, which means more space.&lt;/p&gt;&lt;p&gt;The command to set a page is &lt;b&gt;&lt;p&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is the page name. Any text after this sequence is considered text for the sign. To set the message “Linux Rules” on page A, type the following command:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;pa&gt;Linux Rules" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;It is important to leave extra space at the end so the end of the message is separated from the front of the message as it scrolls. &lt;/p&gt;&lt;p&gt;To delete a page, use &lt;b&gt;&lt;dp&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is the page name. For example, to delete page B, type:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;dpb&gt;" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb3dfb8"&gt;&lt;/a&gt;Displaying Pages&lt;/div&gt;&lt;p&gt;The sign is constantly displaying a page. If the default page A is scrolling by, then when its content is changed it will immediately start displaying the new message. Otherwise, we must tell the sign which page to run using the &lt;b&gt;&lt;rp&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt; command, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is the page to display. Normally, the sign can run only one page at a time.&lt;/p&gt;&lt;p&gt;Once a page has been defined, it can be run. For example, to repeatedly display our message, type:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;rpa&gt;" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Running an undefined page will result in displaying the sign's demo. &lt;/p&gt;&lt;p&gt;Two points of interest for script writers:&lt;/p&gt;&lt;div class="orderedlist"&gt;&lt;ol type="1"&gt;&lt;li&gt;&lt;p&gt;It is possible to update the contents of a page not being displayed, then switch to that page at a later time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It is possible to update the currently displayed message. The only problem is the display will be interrupted mid-message.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;p&gt;Sadly, you cannot ask the sign what the contents of a page are, what page it is currently displaying, or when it has started or ended a display sequence. Thus, techniques like double-buffering don't work for continuous messages. &lt;/p&gt;&lt;p&gt;I have received one terse message from Pro-Lite that alluded to a future version of the sign which is designed to address such needs explicitly for computer users.&lt;/p&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb3e590"&gt;&lt;/a&gt;Timers&lt;/div&gt;&lt;p&gt;In order to display one or more messages at a time, the sign includes ten timers named A to J. Each timer specifies a time and a series of 1 to 32 pages to sequence through. You may repeat pages in a sequence. The time a sequence is displayed consists of a weekday, an hour and a minute, any of which may be wildcarded (*) to match “all”.&lt;/p&gt;&lt;p&gt;When the first timer is defined, the sign is put into “timer” mode and will display that timer's messages immediately. Should two or more timers be defined, the sign seems to wait one minute, then checks each timer to see if one triggered based on the current time. If so, at the end of the displaying message, the new timer's sequence goes into effect. If no rule matches, no change is made.&lt;/p&gt;&lt;p&gt;Note the sign checks the rules for the immediate time. It will not go back to try to find a previous timer. So if you set a timer for 4:15PM and it is now 4:17PM, you've missed the moment when the sign would change.&lt;/p&gt;&lt;p&gt;Should two or more timers both be valid for the current time, the sign unpredictably selects one for display. This means you cannot set one timer to display at 4:15 and another timer to display at 15 minutes past any hour. Both rules would be triggered at 4:15 and it is a toss-up as to which message will be displayed.&lt;/p&gt;&lt;p&gt;The timer command is defined as &lt;b&gt;&lt;t&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;i&gt;&lt;tt&gt;dhhmm&lt;/tt&gt;&lt;/i&gt;ABC&lt;/b&gt;..., where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is the timer, &lt;span class="emphasis"&gt;&lt;em&gt;d&lt;/em&gt;&lt;/span&gt; is 0 (Sunday) to 6 (Saturday) for the day, &lt;span class="emphasis"&gt;&lt;em&gt;hh&lt;/em&gt;&lt;/span&gt; is a two-digit hour and &lt;span class="emphasis"&gt;&lt;em&gt;mm&lt;/em&gt;&lt;/span&gt; is the minute. “ABC...” is a list of 1 to 32 pages to display in the order specified. Note that Page-A and Timer-A are two different, unrelated entities. A timer set for “*****” will be triggered immediately.&lt;/p&gt;&lt;p&gt;The following sequence will display a series of messages at 8:00AM, noon, 1:00PM and 5:00PM:&lt;/p&gt;&lt;pre class="programlisting"&gt;$ cat &gt; /dev/prolite&lt;br /&gt;&lt;id01&gt;&lt;br /&gt;&lt;id01&gt;&lt;pa&gt;Good morning.&lt;br /&gt;&lt;id01&gt;&lt;pb&gt;Have a nice lunch.&lt;br /&gt;&lt;id01&gt;&lt;pc&gt;Get back to work.&lt;br /&gt;&lt;id01&gt;&lt;pd&gt;Have a safe drive home.&lt;br /&gt;&lt;id01&gt;&lt;ta&gt;*0800A&lt;br /&gt;&lt;id01&gt;&lt;tb&gt;*1200B&lt;br /&gt;&lt;id01&gt;&lt;tc&gt;*1300C&lt;br /&gt;&lt;id01&gt;&lt;td&gt;*1700D&lt;br /&gt;ctrl-D&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In order to display a whole sequences of pages, just list more page letters. For instance, it is useful to make a scheme where you assign page letters to different message content. For example, page A could be hourly announcements, page R the runtime status of your machine, page M the message of the day, page T the time and so on. To display several pages right now (including repeats): &lt;/p&gt;&lt;pre class="programlisting"&gt;$ cat &gt; /dev/prolite&lt;br /&gt;&lt;id01&gt;&lt;br /&gt;&lt;id01&gt;&lt;ta&gt;*****TAMARA&lt;br /&gt;ctrl-D&lt;br /&gt;&lt;/pre&gt;   Two interesting tidbits of information: &lt;div class="itemizedlist"&gt;&lt;ul type="disc"&gt;&lt;li&gt;&lt;p&gt;For some reason, the specific time of Sunday at midnight (00000 as a timer value) does not seem to work consistently. I suspect it confuses this value with unset timers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;If a run-page command (&lt;b&gt;&lt;id01&gt;&lt;rpa&gt;&lt;/b&gt;) is issued, the sign is taken out of “timer” mode and displays the requested page. If you then issue the command &lt;b&gt;&lt;id01&gt;&lt;rp*&gt;&lt;/b&gt;, the sign will go back into “timer” mode, displaying the last sequence of messages.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;  To delete a timer, use &lt;b&gt;&lt;dt&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is the timer letter or * for all timers. For example, to delete timer D type: &lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;dtx&gt;" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;   &lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xb3ef88"&gt;&lt;/a&gt;Graphics&lt;/div&gt;&lt;p&gt;There are 26 graphic blocks that can be redefined and are commonly used for graphics. Graphics are inserted into the text via the tag &lt;b&gt;&lt;b&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is a letter from A to Z. For example, this command will display a mug and a wine glass:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;pa&gt;&lt;bw&gt; Party Tonight &lt;bz&gt;"&lt;br /&gt;&gt;\&lt;br /&gt;  /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Altering the graphics requires the &lt;b&gt;&lt;g&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt; command followed by a string of 126 characters made up of R (for red), Y (for yellow), G (for green) and B (for black or unlit). A sequence of seven rows of eighteen LEDs is specified back to back on a single command line. (See Figure 4.) &lt;/p&gt;&lt;div class="mediaobject"&gt;&lt;img src="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f6.png" /&gt;&lt;div class="caption"&gt;&lt;p&gt; Figure 4. A Graphics Block Specification &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;I know at least one user who loads a font into a sequence of graphic blocks, and in this way is able to display more characters than the sign technically allows by default—very clever.&lt;/p&gt;&lt;p&gt;To delete a graphic block, restoring it to the default, use &lt;b&gt;&lt;dg&lt;i&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/i&gt;&gt;&lt;/b&gt;, where &lt;span class="emphasis"&gt;&lt;em&gt;x&lt;/em&gt;&lt;/span&gt; is a letter A to Z; * is a wildcard indicating all are to be deleted.&lt;/p&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xdfcab8"&gt;&lt;/a&gt;Trivia&lt;/div&gt;&lt;p&gt;One additional feature of the sign is to display in sequence a trivia question, your message, the answer to the question and your message again. It works its way though a canned list of questions and then starts over. The sign can be loaded with your own list, which does not have to be trivia. The list can be up to 16KB long, leaving 16KB for the pages. If no list is loaded (i.e., you deleted the trivia), the full 32KB of the sign is available for page content. To make your own list, do the following:&lt;/p&gt;&lt;pre class="programlisting"&gt;$ cat &gt; /dev/prolite&lt;br /&gt;&lt;id01&gt;&lt;br /&gt;&lt;id01&gt;&lt;q+&gt;&lt;br /&gt;&lt;id01&gt;What operating system isn't a pig?&lt;br /&gt;&lt;id01&gt;Linux.&lt;br /&gt;&lt;id01&gt;What operating system is free?&lt;br /&gt;&lt;id01&gt;Linux.&lt;br /&gt;&lt;id01&gt;&lt;q-&gt;&lt;br /&gt;Control-D&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;To delete the trivia, just omit the lines between &lt;b&gt;&lt;q+&gt;&lt;/b&gt; and &lt;b&gt;&lt;q-&gt;&lt;/b&gt;. If no messages are loaded, trivia mode is turned off. If they are, trivia is turned on. &lt;/p&gt;&lt;/div&gt;&lt;div class="simplesect" lang="en"&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xdfcd20"&gt;&lt;/a&gt;Other Useful Commands and Tricks&lt;/div&gt;&lt;p&gt;To reset the sign, removing all timers and pages, use &lt;b&gt;&lt;d*&gt;&lt;/b&gt; like this:&lt;/p&gt;&lt;pre class="programlisting"&gt;echo "&lt;id01&gt;&lt;d*&gt;" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Technically, there is no way to bring the sign to a halt. However, you can take advantage of a quirk in the software to do the same thing. If you use the &lt;b&gt;&lt;fx&gt;&lt;/b&gt; tag in a message to control the speed of the sign, but don't supply a message, the old text isn't cleared and the sign stops scrolling until it gets a new message. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823s1.html"&gt;Function Tags&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Additional tags are shown in “Function Tabs”. European tags are available for characters shown in Figure 5.&lt;/p&gt;&lt;div class="mediaobject"&gt;&lt;a href="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f7.png"&gt;&lt;img src="http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/028/2823/2823f7.inline.png" /&gt;&lt;/a&gt;&lt;div class="caption"&gt;&lt;p&gt; Figure 5. European Characters Available &lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="titlepage"&gt;&lt;a name="N0xa50890.0xdfd248"&gt;&lt;/a&gt;Uses for the Sign&lt;/div&gt;&lt;p&gt;It doesn't take much to make the sign useful. For example, scripts that send commands to the sign can be executed every few minutes by editing your crontab file (&lt;b&gt;crontab -e&lt;/b&gt;) to include:&lt;/p&gt;&lt;pre class="programlisting"&gt;*/5 * * * * /usr/local/bin/sign 1&gt; /dev/null \&lt;br /&gt;2&gt; /dev/null&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Every five minutes, the system will call /usr/local/bin/sign. In this script, we can place any number of tasks. To show our uptime, add these lines: &lt;/p&gt;&lt;pre class="programlisting"&gt;#!/bin/bash&lt;br /&gt;stty 0:705:bd:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:12\&lt;br /&gt;:f:17:16:0:0:73 &lt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;pu&gt;'uptime' " &gt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;ta&gt;*****U" &gt; /dev/prolite&lt;br /&gt;&lt;/pre&gt;   If root wants to see the last line of the log file scroll by, this command will suffice: &lt;pre class="programlisting"&gt;tail -f -n 1 /var/log/messages |&lt;br /&gt;  awk '{ print "&lt;id01&gt;&lt;pa&gt;" $0 " "; }' &gt;&lt;br /&gt;  /dev/prolite &amp;amp;&lt;br /&gt;&lt;/pre&gt;   This job sits in the background, getting lines from the end of the log as they come in, prefixes a &lt;b&gt;&lt;id01&gt;&lt;pa&gt;&lt;/b&gt; to it and sends it to the sign. The process then goes to sleep until another log entry is made. The only reason to run as root is to get access to the messages file. &lt;p&gt;The sign can also act as a watchdog for our system by setting up a timer to go off several minutes later. Ideally, the sign will get updated before the timer goes off and the timer will again be set for some time in the future. In the event the sign is not updated, the timer trips and an alternate alert message is displayed.&lt;/p&gt;&lt;pre class="programlisting"&gt;!/bin/bash&lt;br /&gt;stty 0:705:bd:0:3:1c:7f:15:4:0:1:0:11:13:1a:0:12\&lt;br /&gt;:f:17:16:0:0:73 &lt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;pu&gt;&lt;fd&gt;Server Up" &gt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;dtb&gt;" &gt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;ta&gt;00001U" &gt; /dev/prolite&lt;br /&gt;echo "&lt;id01&gt;&lt;td&gt;&lt;fb&gt;&lt;cc&gt;Server Down" &gt; \&lt;br /&gt;  /dev/prolite&lt;br /&gt;date "+&lt;id01&gt;&lt;tb&gt;*%H%MD" -date "7 min" &gt; \&lt;br /&gt;  /dev/prolite&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;To do this relies on some tricks. First, you cannot use a generic timer (&lt;b&gt;&lt;ta&gt;*****&lt;/b&gt;) for running standard messages because it conflicts with our watchdog timer. Secondly, we cannot use timer &lt;b&gt;&lt;ta&gt;00000&lt;/b&gt; because it confuses the sign. Thus, we have to use one minute after midnight on Sunday (&lt;b&gt;&lt;ta&gt;00001&lt;/b&gt;) in order to display our messages. When no timers are defined, the first timer defined shows our page. &lt;/p&gt;&lt;p&gt;Deleting timer B keeps us using timer A, which shows normal text. The sign ignores requests to delete timers and pages that don't exist. Once page A is defined and displaying, we define page B in the background and set up a time, again using the clever &lt;span class="bold"&gt;&lt;b&gt;date&lt;/b&gt;&lt;/span&gt; command to output it seven minutes from now. Since our cron job is set to run this script every five minutes, the timer should never go off unless something is wrong.&lt;/p&gt;&lt;p&gt;If Linux suffers a power failure, the cron daemon is killed, or the sign becomes disconnected, it will display a warning message. The tag &lt;b&gt;&lt;fd&gt;&lt;/b&gt; indicates the message should instantly appear instead of scrolling, where &lt;b&gt;&lt;fb&gt;&lt;/b&gt; indicates the text should appear from the center—this will get your attention quickly.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="content"&gt;     &lt;p&gt;I have a led board which has 2 lines and 120x16 leds. The protocol described on this page is simular to the protocol used in my led board only it has some kind of security code in it.&lt;/p&gt; &lt;p&gt;For example:&lt;br /&gt;This wil return a ACK, and the led board will show the message:&lt;br /&gt;&lt;id01&gt;&lt;l1&gt;&lt;pa&gt;&lt;fe&gt;&lt;ma&gt;&lt;wc&gt;&lt;fe&gt;test62&lt;e&gt;&lt;/p&gt; &lt;p&gt;This wil return a NACK, and the led board does not change:&lt;br /&gt;&lt;id01&gt;&lt;l1&gt;&lt;pa&gt;&lt;fe&gt;&lt;ma&gt;&lt;wc&gt;&lt;fe&gt;test80&lt;e&gt;&lt;/p&gt; &lt;p&gt;So there is a code right after the text... Another example:&lt;br /&gt;&lt;id01&gt;&lt;l1&gt;&lt;pa&gt;&lt;fe&gt;&lt;ma&gt;&lt;wc&gt;&lt;fe&gt;Leon ter Linden1B&lt;e&gt; = ACK&lt;br /&gt;&lt;id01&gt;&lt;l2&gt;&lt;pa&gt;&lt;fe&gt;&lt;ma&gt;&lt;wc&gt;&lt;fe&gt;Leon ter Linden43&lt;e&gt; = NACK&lt;/p&gt; &lt;p&gt;Does anyone know how to calculate the code that comes after the text?&lt;/p&gt;   &lt;/div&gt;   &lt;div class="links"&gt;     &lt;ul class="links"&gt;&lt;li class="first comment_reply"&gt;&lt;a href="http://www.linuxjournal.com/comment/reply/2823/157707" class="comment_reply"&gt;reply&lt;/a&gt;&lt;/li&gt;&lt;li class="last print"&gt;&lt;a href="http://www.linuxjournal.com/print/2823" title="Display a printer-friendly version of this page." class="print-page print"&gt;Printer-friendly version&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;/div&gt;      &lt;div class="head"&gt;             &lt;h3&gt;&lt;a href="http://www.linuxjournal.com/article/2823#comment-191626" class="active"&gt;xor checksum&lt;/a&gt;&lt;/h3&gt;     &lt;h4&gt;On October 16th, 2006 Are (not verified) says:&lt;/h4&gt;   &lt;/div&gt;        &lt;p&gt;Here is the code to calculate the checksum.&lt;br /&gt;The checksum is an xor of all the characters sent, without the first ID tag and without the end E tag.&lt;/p&gt; &lt;p&gt;&lt;code&gt;&lt;br /&gt;static unsigned char&lt;br /&gt;checksum(const char *str, unsigned char init)&lt;br /&gt;{&lt;br /&gt;        unsigned char i = init;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;        while (*str != '\0') {&lt;br /&gt;                i ^= *str;&lt;br /&gt;                str++;&lt;br /&gt;        }&lt;/p&gt; &lt;p&gt;        return (i);&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;int&lt;br /&gt;main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;        unsigned char csum = 0x0;&lt;/p&gt; &lt;p&gt;        if (argc != 2)&lt;br /&gt;                exit(-1);&lt;br /&gt;        else&lt;br /&gt;                msg = argv[1];&lt;/p&gt;         csum = checksum(msg, csum);&lt;br /&gt;        printf("%02X\n",csum);&lt;br /&gt;        return (csum);&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-5976188275431572415?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/5976188275431572415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=5976188275431572415' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/5976188275431572415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/5976188275431572415'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/07/port-setting-from-linux-journel.html' title='port setting from linux journel'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-2312196180906972262</id><published>2008-07-10T21:59:00.000-07:00</published><updated>2008-07-10T22:01:38.053-07:00</updated><title type='text'>Serial Communications in Win32</title><content type='html'>Serial Communications in Win32&lt;br /&gt;&lt;br /&gt;　&lt;br /&gt;&lt;br /&gt;Allen Denver&lt;br /&gt;Microsoft Windows Developer Support&lt;br /&gt;&lt;br /&gt;December 11, 1995&lt;br /&gt;&lt;br /&gt;Allen seldom eats breakfast, but if he had to pick a favorite, Win32 serial communications would be the top choice.&lt;br /&gt;&lt;br /&gt;Click to open or copy the files in the MTTTY sample application for this technical article.&lt;br /&gt;&lt;br /&gt;　&lt;br /&gt;Abstract&lt;br /&gt;&lt;br /&gt;Serial communications in Microsoft?Win32?is significantly different from serial communications in 16-bit Microsoft Windows? Those familiar with 16-bit serial communications functions will have to relearn many parts of the system to program serial communications properly. This article will help to accomplish this. Those unfamiliar with serial communications will find this article a helpful foundation for development efforts.&lt;br /&gt;&lt;br /&gt;This article assumes the reader is familiar with the fundamentals of multiple threading and synchronization in Win32. In addition, a basic familiarity of the Win32 heap functions is useful to fully comprehend the memory management methods used by the sample, MTTTY, included with this article. For more information regarding these functions, consult the Platform SDK documentation, the Microsoft Win32 SDK Knowledge Base, or the Microsoft Developer Network Library. Application programming interfaces (APIs) that control user interface features of windows and dialog boxes, though not discussed here, are useful to know in order to fully comprehend the sample provided with this article. Readers unfamiliar with general Windows programming practices should learn some of the fundamentals of general Windows programming before taking on serial communications. In other words, get your feet wet before diving in head first.&lt;br /&gt;Introduction&lt;br /&gt;&lt;br /&gt;The focus of this article is on application programming interfaces (APIs) and methods that are compatible with Microsoft?Windows NT?and Windows 95; therefore, APIs supported on both platforms are the only ones discussed. Windows 95 supports the Win32?Telephony API (TAPI) and Windows NT 3.x does not; therefore, this discussion will not include TAPI. TAPI does deserve mention, however, in that it very nicely implements modem interfacing and call controlling. A production application that works with modems and makes telephone calls should implement these features using the TAPI interface. This will allow seamless integration with the other TAPI-enabled applications that a user may have. Furthermore, this article does not discuss some of the configuration functions in Win32, such as GetCommProperties.&lt;br /&gt;&lt;br /&gt;The article is broken into the following sections: Opening a port, reading and writing (nonoverlapped and overlapped), serial status (events and errors), and serial settings (DCB, flow control, and communications time-outs).&lt;br /&gt;&lt;br /&gt;The sample included with this article, MTTTY: Multithreaded TTY, implements many of the features discussed here. It uses three threads in its implementation: a user interface thread that does memory management, a writer thread that controls all writing, and a reader/status thread that reads data and handles status changes on the port. The sample employs a few different data heaps for memory management. It also makes extensive use of synchronization methods to facilitate communication between threads.&lt;br /&gt;Opening a Port&lt;br /&gt;&lt;br /&gt;The CreateFile function opens a communications port. There are two ways to call CreateFile to open the communications port: overlapped and nonoverlapped. The following is the proper way to open a communications resource for overlapped operation:&lt;br /&gt;&lt;br /&gt;HANDLE hComm;&lt;br /&gt;&lt;br /&gt;hComm = CreateFile( gszPort,  &lt;br /&gt;&lt;br /&gt;                    GENERIC_READ | GENERIC_WRITE, &lt;br /&gt;&lt;br /&gt;                    0, &lt;br /&gt;&lt;br /&gt;                    0, &lt;br /&gt;&lt;br /&gt;                    OPEN_EXISTING,&lt;br /&gt;&lt;br /&gt;                    FILE_FLAG_OVERLAPPED,&lt;br /&gt;&lt;br /&gt;                    0);&lt;br /&gt;&lt;br /&gt;if (hComm == INVALID_HANDLE_VALUE)&lt;br /&gt;&lt;br /&gt;   // error opening port; abort&lt;br /&gt;&lt;br /&gt;Removal of the FILE_FLAG_OVERLAPPED flag from the call to CreateFile specifies nonoverlapped operation. The next section discusses overlapped and nonoverlapped operations.&lt;br /&gt;&lt;br /&gt;The Platform SDK documentation states that when opening a communications port, the call to CreateFile has the following requirements:&lt;br /&gt;&lt;br /&gt;    * fdwShareMode must be zero. Communications ports cannot be shared in the same manner that files are shared. Applications using TAPI can use the TAPI functions to facilitate sharing resources between applications. For Win32 applications not using TAPI, handle inheritance or duplication is necessary to share the communications port. Handle duplication is beyond the scope of this article; please refer to the Platform SDK documentation for more information.&lt;br /&gt;    * fdwCreate must specify the OPEN_EXISTING flag.&lt;br /&gt;    * hTemplateFile parameter must be NULL.&lt;br /&gt;&lt;br /&gt;One thing to note about port names is that traditionally they have been COM1, COM2, COM3, or COM4. The Win32 API does not provide any mechanism for determining what ports exist on a system. Windows NT and Windows 95 keep track of installed ports differently from one another, so any one method would not be portable across all Win32 platforms. Some systems even have more ports than the traditional maximum of four. Hardware vendors and serial-device-driver writers are free to name the ports anything they like. For this reason, it is best that users have the ability to specify the port name they want to use. If a port does not exist, an error will occur (ERROR_FILE_NOT_FOUND) after attempting to open the port, and the user should be notified that the port isn’t available.&lt;br /&gt;Reading and Writing&lt;br /&gt;&lt;br /&gt;Reading from and writing to communications ports in Win32 is very similar to file input/output (I/O) in Win32. In fact, the functions that accomplish file I/O are the same functions used for serial I/O. I/O in Win32 can be done either of two ways: overlapped or nonoverlapped. The Platform SDK documentation uses the terms asynchronous and synchronous to connote these types of I/O operations. This article, however, uses the terms overlapped and nonoverlapped.&lt;br /&gt;&lt;br /&gt;Nonoverlapped I/O is familiar to most developers because this is the traditional form of I/O, where an operation is requested and is assumed to be complete when the function returns. In the case of overlapped I/O, the system may return to the caller immediately even when an operation is not finished and will signal the caller when the operation completes. The program may use the time between the I/O request and its completion to perform some “background?work.&lt;br /&gt;&lt;br /&gt;Reading and writing in Win32 is significantly different from reading and writing serial communications ports in 16-bit Windows. 16-bit Windows only has the ReadComm and WriteComm functions. Win32 reading and writing can involve many more functions and choices. These issues are discussed below.&lt;br /&gt;Nonoverlapped I/O&lt;br /&gt;&lt;br /&gt;Nonoverlapped I/O is very straightforward, though it has limitations. An operation takes place while the calling thread is blocked. Once the operation is complete, the function returns and the thread can continue its work. This type of I/O is useful for multithreaded applications because while one thread is blocked on an I/O operation, other threads can still perform work. It is the responsibility of the application to serialize access to the port correctly. If one thread is blocked waiting for its I/O operation to complete, all other threads that subsequently call a communications API will be blocked until the original operation completes. For instance, if one thread were waiting for a ReadFile function to return, any other thread that issued a WriteFile function would be blocked.&lt;br /&gt;&lt;br /&gt;One of the many factors to consider when choosing between nonoverlapped and overlapped operations is portability. Overlapped operation is not a good choice because most operating systems do not support it. Most operating systems support some form of multithreading, however, so multithreaded nonoverlapped I/O may be the best choice for portability reasons.&lt;br /&gt;Overlapped I/O&lt;br /&gt;&lt;br /&gt;Overlapped I/O is not as straightforward as nonoverlapped I/O, but allows more flexibility and efficiency. A port open for overlapped operations allows multiple threads to do I/O operations at the same time and perform other work while the operations are pending. Furthermore, the behavior of overlapped operations allows a single thread to issue many different requests and do work in the background while the operations are pending.&lt;br /&gt;&lt;br /&gt;In both single-threaded and multithreaded applications, some synchronization must take place between issuing requests and processing the results. One thread will have to be blocked until the result of an operation is available. The advantage is that overlapped I/O allows a thread to do some work between the time of the request and its completion. If no work can be done, then the only case for overlapped I/O is that it allows for better user responsiveness.&lt;br /&gt;&lt;br /&gt;Overlapped I/O is the type of operation that the MTTTY sample uses. It creates a thread that is responsible for reading the port’s data and reading the port’s status. It also performs periodic background work. The program creates another thread exclusively for writing data out the port.&lt;br /&gt;&lt;br /&gt;Note   Applications sometimes abuse multithreading systems by creating too many threads. Although using multiple threads can resolve many difficult problems, creating excessive threads is not the most efficient use of them in an application. Threads are less a strain on the system than processes but still require system resources such as CPU time and memory. An application that creates excessive threads may adversely affect the performance of the entire system. A better use of threads is to create a different request queue for each type of job and to have a worker thread issue an I/O request for each entry in the request queue. This method is used by the MTTTY sample provided with this article.&lt;br /&gt;&lt;br /&gt;An overlapped I/O operation has two parts: the creation of the operation and the detection of its completion. Creating the operation entails setting up an OVERLAPPED structure, creating a manual-reset event for synchronization, and calling the appropriate function (ReadFile or WriteFile). The I/O operation may or may not be completed immediately. It is an error for an application to assume that a request for an overlapped operation always yields an overlapped operation. If an operation is completed immediately, an application needs to be ready to continue processing normally. The second part of an overlapped operation is to detect its completion. Detecting completion of the operation involves waiting for the event handle, checking the overlapped result, and then handling the data. The reason that there is more work involved with an overlapped operation is that there are more points of failure. If a nonoverlapped operation fails, the function just returns an error-return result. If an overlapped operation fails, it can fail in the creation of the operation or while the operation is pending. You may also have a time-out of the operation or a time-out waiting for the signal that the operation is complete.&lt;br /&gt;Reading&lt;br /&gt;&lt;br /&gt;The ReadFile function issues a read operation. ReadFileEx also issues a read operation, but since it is not available on Windows 95, it is not discussed in this article. Here is a code snippet that details how to issue a read request. Notice that the function calls a function to process the data if the ReadFile returns TRUE. This is the same function called if the operation becomes overlapped. Note the fWaitingOnRead flag that is defined by the code; it indicates whether or not a read operation is overlapped. It is used to prevent the creation of a new read operation if one is outstanding.&lt;br /&gt;&lt;br /&gt;DWORD dwRead;&lt;br /&gt;&lt;br /&gt;BOOL fWaitingOnRead = FALSE;&lt;br /&gt;&lt;br /&gt;OVERLAPPED osReader = {0};&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;// Create the overlapped event. Must be closed before exiting&lt;br /&gt;&lt;br /&gt;// to avoid a handle leak.&lt;br /&gt;&lt;br /&gt;osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (osReader.hEvent == NULL)&lt;br /&gt;&lt;br /&gt;   // Error creating overlapped event; abort.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (!fWaitingOnRead) {&lt;br /&gt;&lt;br /&gt;   // Issue read operation.&lt;br /&gt;&lt;br /&gt;   if (!ReadFile(hComm, lpBuf, READ_BUF_SIZE, &amp;dwRead, &amp;osReader)) {&lt;br /&gt;&lt;br /&gt;      if (GetLastError() != ERROR_IO_PENDING)     // read not delayed?&lt;br /&gt;&lt;br /&gt;         // Error in communications; report it.&lt;br /&gt;&lt;br /&gt;      else&lt;br /&gt;&lt;br /&gt;         fWaitingOnRead = TRUE;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else {    &lt;br /&gt;&lt;br /&gt;      // read completed immediately&lt;br /&gt;&lt;br /&gt;      HandleASuccessfulRead(lpBuf, dwRead);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The second part of the overlapped operation is the detection of its completion. The event handle in the OVERLAPPED structure is passed to the WaitForSingleObject function, which will wait until the object is signaled. Once the event is signaled, the operation is complete. This does not mean that it was completed successfully, just that it was completed. The GetOverlappedResult function reports the result of the operation. If an error occurred, GetOverlappedResult returns FALSE and GetLastError returns the error code. If the operation was completed successfully, GetOverlappedResult will return TRUE.&lt;br /&gt;&lt;br /&gt;Note   GetOverlappedResult can detect completion of the operation, as well as return the operation’s failure status. GetOverlappedResult returns FALSE and GetLastError returns ERROR_IO_INCOMPLETE when the operation is not completed. In addition, GetOverlappedResult can be made to block until the operation completes. This effectively turns the overlapped operation into a nonoverlapped operation and is accomplished by passing TRUE as the bWait parameter.&lt;br /&gt;&lt;br /&gt;Here is a code snippet that shows one way to detect the completion of an overlapped read operation. Note that the code calls the same function to process the data that was called when the operation completed immediately. Also note the use of the fWaitingOnRead flag. Here it controls entry into the detection code, since it should be called only when an operation is outstanding.&lt;br /&gt;&lt;br /&gt;#define READ_TIMEOUT      500      // milliseconds&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;DWORD dwRes;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (fWaitingOnRead) {&lt;br /&gt;&lt;br /&gt;   dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);&lt;br /&gt;&lt;br /&gt;   switch(dwRes)&lt;br /&gt;&lt;br /&gt;   {&lt;br /&gt;&lt;br /&gt;      // Read completed.&lt;br /&gt;&lt;br /&gt;      case WAIT_OBJECT_0:&lt;br /&gt;&lt;br /&gt;          if (!GetOverlappedResult(hComm, &amp;osReader, &amp;dwRead, FALSE))&lt;br /&gt;&lt;br /&gt;             // Error in communications; report it.&lt;br /&gt;&lt;br /&gt;          else&lt;br /&gt;&lt;br /&gt;             // Read completed successfully.&lt;br /&gt;&lt;br /&gt;             HandleASuccessfulRead(lpBuf, dwRead);&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;          //  Reset flag so that another opertion can be issued.&lt;br /&gt;&lt;br /&gt;          fWaitingOnRead = FALSE;&lt;br /&gt;&lt;br /&gt;          break;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;      case WAIT_TIMEOUT:&lt;br /&gt;&lt;br /&gt;          // Operation isn't complete yet. fWaitingOnRead flag isn't&lt;br /&gt;&lt;br /&gt;          // changed since I'll loop back around, and I don't want&lt;br /&gt;&lt;br /&gt;          // to issue another read until the first one finishes.&lt;br /&gt;&lt;br /&gt;          //&lt;br /&gt;&lt;br /&gt;          // This is a good time to do some background work.&lt;br /&gt;&lt;br /&gt;          break;                       &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;      default:&lt;br /&gt;&lt;br /&gt;          // Error in the WaitForSingleObject; abort.&lt;br /&gt;&lt;br /&gt;          // This indicates a problem with the OVERLAPPED structure's&lt;br /&gt;&lt;br /&gt;          // event handle.&lt;br /&gt;&lt;br /&gt;          break;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Writing&lt;br /&gt;&lt;br /&gt;Transmitting data out the communications port is very similar to reading in that it uses a lot of the same APIs. The code snippet below demonstrates how to issue and wait for a write operation to be completed.&lt;br /&gt;&lt;br /&gt;BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   OVERLAPPED osWrite = {0};&lt;br /&gt;&lt;br /&gt;   DWORD dwWritten;&lt;br /&gt;&lt;br /&gt;   DWORD dwRes;&lt;br /&gt;&lt;br /&gt;   BOOL fRes;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Create this write operation's OVERLAPPED structure's hEvent.&lt;br /&gt;&lt;br /&gt;   osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);&lt;br /&gt;&lt;br /&gt;   if (osWrite.hEvent == NULL)&lt;br /&gt;&lt;br /&gt;      // error creating overlapped event handle&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Issue write.&lt;br /&gt;&lt;br /&gt;   if (!WriteFile(hComm, lpBuf, dwToWrite, &amp;dwWritten, &amp;osWrite)) {&lt;br /&gt;&lt;br /&gt;      if (GetLastError() != ERROR_IO_PENDING) { &lt;br /&gt;&lt;br /&gt;         // WriteFile failed, but isn't delayed. Report error and abort.&lt;br /&gt;&lt;br /&gt;         fRes = FALSE;&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      else&lt;br /&gt;&lt;br /&gt;         // Write is pending.&lt;br /&gt;&lt;br /&gt;         dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);&lt;br /&gt;&lt;br /&gt;         switch(dwRes)&lt;br /&gt;&lt;br /&gt;         {&lt;br /&gt;&lt;br /&gt;            // OVERLAPPED structure's event has been signaled. &lt;br /&gt;&lt;br /&gt;            case WAIT_OBJECT_0:&lt;br /&gt;&lt;br /&gt;                 if (!GetOverlappedResult(hComm, &amp;osWrite, &amp;dwWritten, FALSE))&lt;br /&gt;&lt;br /&gt;                       fRes = FALSE;&lt;br /&gt;&lt;br /&gt;                 else&lt;br /&gt;&lt;br /&gt;                  // Write operation completed successfully.&lt;br /&gt;&lt;br /&gt;                  fRes = TRUE;&lt;br /&gt;&lt;br /&gt;                 break;&lt;br /&gt;&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;            default:&lt;br /&gt;&lt;br /&gt;                 // An error has occurred in WaitForSingleObject.&lt;br /&gt;&lt;br /&gt;                 // This usually indicates a problem with the&lt;br /&gt;&lt;br /&gt;                // OVERLAPPED structure's event handle.&lt;br /&gt;&lt;br /&gt;                 fRes = FALSE;&lt;br /&gt;&lt;br /&gt;                 break;&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // WriteFile completed immediately.&lt;br /&gt;&lt;br /&gt;      fRes = TRUE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   CloseHandle(osWrite.hEvent);&lt;br /&gt;&lt;br /&gt;   return fRes;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Notice that the code above uses the WaitForSingleObject function with a time-out value of INFINITE. This causes the WaitForSingleObject function to wait forever until the operation is completed; this may make the thread or program appear to be “hung?when, in fact, the write operation is simply taking a long time to complete or flow control has blocked the transmission. Status checking, discussed later, can detect this condition, but doesn’t cause the WaitForSingleObject to return. Three things can alleviate this condition:&lt;br /&gt;&lt;br /&gt;    * Place the code in a separate thread. This allows other threads to execute any functions they desire while our writer thread waits for the write to be completed. This is what the MTTTY sample does.&lt;br /&gt;    * Use COMMTIMEOUTS to cause the write to be completed after a time-out period has passed. This is discussed more fully in the “Communications Time-outs?section later in this article. This is also what the MTTTY sample allows.&lt;br /&gt;    * Change the WaitForSingleObject call to include a real time-out value. This causes more problems because if the program issues another operation while an older operation is still pending, new OVERLAPPED structures and overlapped events need to be allocated. This type of recordkeeping is difficult, particularly when compared to using a “job queue?design for the operations. The “job queue?method is used in the MTTTY sample.&lt;br /&gt;&lt;br /&gt;Note: The time-out values in synchronization functions are not communications time-outs. Synchronization time-outs cause WaitForSingleObject or WaitForMultipleObjects to return WAIT_TIMEOUT. This is not the same as a read or write operation timing out. Communications time-outs are described later in this article.&lt;br /&gt;&lt;br /&gt;Because the WaitForSingleObject function in the above code snippet uses an INFINITE time-out, it is equivalent to using GetOverlappedResult with TRUE for the fWait parameter. Here is equivalent code in a much simplified form:&lt;br /&gt;&lt;br /&gt;BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   OVERLAPPED osWrite = {0};&lt;br /&gt;&lt;br /&gt;   DWORD dwWritten;&lt;br /&gt;&lt;br /&gt;   BOOL fRes;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Create this writes OVERLAPPED structure hEvent.&lt;br /&gt;&lt;br /&gt;   osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);&lt;br /&gt;&lt;br /&gt;   if (osWrite.hEvent == NULL)&lt;br /&gt;&lt;br /&gt;      // Error creating overlapped event handle.&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Issue write.&lt;br /&gt;&lt;br /&gt;   if (!WriteFile(hComm, lpBuf, dwToWrite, &amp;dwWritten, &amp;osWrite)) {&lt;br /&gt;&lt;br /&gt;      if (GetLastError() != ERROR_IO_PENDING) { &lt;br /&gt;&lt;br /&gt;         // WriteFile failed, but it isn't delayed. Report error and abort.&lt;br /&gt;&lt;br /&gt;         fRes = FALSE;&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      else {&lt;br /&gt;&lt;br /&gt;         // Write is pending.&lt;br /&gt;&lt;br /&gt;         if (!GetOverlappedResult(hComm, &amp;osWrite, &amp;dwWritten, TRUE))&lt;br /&gt;&lt;br /&gt;            fRes = FALSE;&lt;br /&gt;&lt;br /&gt;         else&lt;br /&gt;&lt;br /&gt;            // Write operation completed successfully.&lt;br /&gt;&lt;br /&gt;            fRes = TRUE;&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // WriteFile completed immediately.&lt;br /&gt;&lt;br /&gt;      fRes = TRUE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   CloseHandle(osWrite.hEvent);&lt;br /&gt;&lt;br /&gt;   return fRes;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;GetOverlappedResult is not always the best way to wait for an overlapped operation to be completed. For example, if an application needs to wait on another event handle, the first code snippet serves as a better model than the second. The call to WaitForSingleObject is easy to change to WaitForMultipleObjects to include the additional handles on which to wait. This is what the MTTTY sample application does.&lt;br /&gt;&lt;br /&gt;A common mistake in overlapped I/O is to reuse an OVERLAPPED structure before the previous overlapped operation is completed. If a new overlapped operation is issued before a previous operation is completed, a new OVERLAPPED structure must be allocated for it. A new manual-reset event for the hEvent member of the OVERLAPPED structure must also be created. Once an overlapped operation is complete, the OVERLAPPED structure and its event are free for reuse.&lt;br /&gt;&lt;br /&gt;The only member of the OVERLAPPED structure that needs modifying for serial communications is the hEvent member. The other members of the OVERLAPPED structure should be initialized to zero and left alone. Modifying the other members of the OVERLAPPED structure is not necessary for serial communications devices. The documentation for ReadFile and WriteFile state that the Offset and OffsetHigh members of the OVERLAPPED structure must be updated by the application, or else results are unpredictable. This guideline should be applied to OVERLAPPED structures used for other types of resources, such as files.&lt;br /&gt;Serial Status&lt;br /&gt;&lt;br /&gt;There are two methods to retrieve the status of a communications port. The first is to set an event mask that causes notification of the application when the desired events occur. The SetCommMask function sets this event mask, and the WaitCommEvent function waits for the desired events to occur. These functions are similar to the 16-bit functions SetCommEventMask and EnableCommNotification, except that the Win32 functions do not post WM_COMMNOTIFY messages. In fact, the WM_COMMNOTIFY message is not even part of the Win32 API. The second method for retrieving the status of the communications port is to periodically call a few different status functions. Polling is, of course, neither efficient nor recommended.&lt;br /&gt;Communications Events&lt;br /&gt;&lt;br /&gt;Communications events can occur at any time in the course of using a communications port. The two steps involved in receiving notification of communications events are as follows:&lt;br /&gt;&lt;br /&gt;    * SetCommMask sets the desired events that cause a notification.&lt;br /&gt;    * WaitCommEvent issues a status check. The status check can be an overlapped or nonoverlapped operation, just as the read and write operations can be.&lt;br /&gt;&lt;br /&gt;Note: The word event in this context refers to communications events only. It does not refer to an event object used for synchronization.&lt;br /&gt;&lt;br /&gt;Here is an example of the SetCommMask function:&lt;br /&gt;&lt;br /&gt;DWORD dwStoredFlags;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;dwStoredFlags = EV_BREAK | EV_CTS   | EV_DSR | EV_ERR | EV_RING |\&lt;br /&gt;&lt;br /&gt;                EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;&lt;br /&gt;&lt;br /&gt;if (!SetCommMask(hComm, dwStoredFlags))&lt;br /&gt;&lt;br /&gt;   // error setting communications mask&lt;br /&gt;&lt;br /&gt;A description of each type of event is in Table 1.&lt;br /&gt;&lt;br /&gt;Table 1. Communications Event Flags&lt;br /&gt;&lt;br /&gt;Event Flag&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Description&lt;br /&gt;&lt;br /&gt;EV_BREAK&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;A break was detected on input.&lt;br /&gt;&lt;br /&gt;EV_CTS&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The CTS (clear-to-send) signal changed state. To get the actual state of the CTS line, GetCommModemStatus should be called.&lt;br /&gt;&lt;br /&gt;EV_DSR&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The DSR (data-set-ready) signal changed state. To get the actual state of the DSR line, GetCommModemStatus should be called.&lt;br /&gt;&lt;br /&gt;EV_ERR&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. To find the cause of the error, ClearCommError should be called.&lt;br /&gt;&lt;br /&gt;EV_RING&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;A ring indicator was detected.&lt;br /&gt;&lt;br /&gt;EV_RLSD&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The RLSD (receive-line-signal-detect) signal changed state. To get the actual state of the RLSD line, GetCommModemStatus should be called. Note that this is commonly referred to as the CD (carrier detect) line.&lt;br /&gt;&lt;br /&gt;EV_RXCHAR&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;A new character was received and placed in the input buffer. See the “Caveat?section below for a discussion of this flag.&lt;br /&gt;&lt;br /&gt;EV_RXFLAG&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The event character was received and placed in the input buffer. The event character is specified in the EvtChar member of the DCB structure discussed later. The “Caveat?section below also applies to this flag.&lt;br /&gt;&lt;br /&gt;EV_TXEMPTY&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The last character in the output buffer was sent to the serial port device. If a hardware buffer is used, this flag only indicates that all data has been sent to the hardware. There is no way to detect when the hardware buffer is empty without talking directly to the hardware with a device driver.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;After specifying the event mask, the WaitCommEvent function detects the occurrence of the events. If the port is open for nonoverlapped operation, then the WaitCommEvent function does not contain an OVERLAPPED structure. The function blocks the calling thread until the occurrence of one of the events. If an event never occurs, the thread may block indefinitely.&lt;br /&gt;&lt;br /&gt;Here is a code snippet that shows how to wait for an EV_RING event when the port is open for nonoverlapped operation:&lt;br /&gt;&lt;br /&gt;   DWORD dwCommEvent;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   if (!SetCommMask(hComm, EV_RING))&lt;br /&gt;&lt;br /&gt;      // Error setting communications mask&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   if (!WaitCommEvent(hComm, &amp;dwCommEvent, NULL))&lt;br /&gt;&lt;br /&gt;      // An error occurred waiting for the event.&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // Event has occurred.&lt;br /&gt;&lt;br /&gt;      return TRUE;&lt;br /&gt;&lt;br /&gt;Note   The Microsoft Win32 SDK Knowledge Base documents a problem with Windows 95 and the EV_RING flag. The above code never returns in Windows 95 because the EV_RING event is not detected by the system; Windows NT properly reports the EV_RING event. Please see the Win32 SDK Knowledge Base for more information on this bug.&lt;br /&gt;&lt;br /&gt;As noted, the code above can be blocked forever if an event never occurs. A better solution would be to open the port for overlapped operation and wait for a status event in the following manner:&lt;br /&gt;&lt;br /&gt;   #define STATUS_CHECK_TIMEOUT      500   // Milliseconds&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   DWORD      dwRes;&lt;br /&gt;&lt;br /&gt;   DWORD      dwCommEvent;&lt;br /&gt;&lt;br /&gt;   DWORD      dwStoredFlags;&lt;br /&gt;&lt;br /&gt;   BOOL      fWaitingOnStat = FALSE;&lt;br /&gt;&lt;br /&gt;   OVERLAPPED osStatus = {0};&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\&lt;br /&gt;&lt;br /&gt;                  EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;&lt;br /&gt;&lt;br /&gt;   if (!SetCommMask(comHandle, dwStoredFlags))&lt;br /&gt;&lt;br /&gt;      // error setting communications mask; abort&lt;br /&gt;&lt;br /&gt;      return 0;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);&lt;br /&gt;&lt;br /&gt;   if (osStatus.hEvent == NULL)&lt;br /&gt;&lt;br /&gt;      // error creating event; abort&lt;br /&gt;&lt;br /&gt;      return 0;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   for ( ; ; ) {&lt;br /&gt;&lt;br /&gt;      // Issue a status event check if one hasn't been issued already.&lt;br /&gt;&lt;br /&gt;      if (!fWaitingOnStat) {&lt;br /&gt;&lt;br /&gt;         if (!WaitCommEvent(hComm, &amp;dwCommEvent, &amp;osStatus)) {&lt;br /&gt;&lt;br /&gt;            if (GetLastError() == ERROR_IO_PENDING)&lt;br /&gt;&lt;br /&gt;               bWaitingOnStatusHandle = TRUE;&lt;br /&gt;&lt;br /&gt;            else&lt;br /&gt;&lt;br /&gt;               // error in WaitCommEvent; abort&lt;br /&gt;&lt;br /&gt;               break;&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         else&lt;br /&gt;&lt;br /&gt;            // WaitCommEvent returned immediately.&lt;br /&gt;&lt;br /&gt;            // Deal with status event as appropriate.&lt;br /&gt;&lt;br /&gt;            ReportStatusEvent(dwCommEvent); &lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;      // Check on overlapped operation.&lt;br /&gt;&lt;br /&gt;      if (fWaitingOnStat) {&lt;br /&gt;&lt;br /&gt;         // Wait a little while for an event to occur.&lt;br /&gt;&lt;br /&gt;         dwRes = WaitForSingleObject(osStatus.hEvent, STATUS_CHECK_TIMEOUT);&lt;br /&gt;&lt;br /&gt;         switch(dwRes)&lt;br /&gt;&lt;br /&gt;         {&lt;br /&gt;&lt;br /&gt;             // Event occurred.&lt;br /&gt;&lt;br /&gt;             case WAIT_OBJECT_0: &lt;br /&gt;&lt;br /&gt;                 if (!GetOverlappedResult(hComm, &amp;osStatus, &amp;dwOvRes, FALSE))&lt;br /&gt;&lt;br /&gt;                    // An error occurred in the overlapped operation;&lt;br /&gt;&lt;br /&gt;                    // call GetLastError to find out what it was&lt;br /&gt;&lt;br /&gt;                    // and abort if it is fatal.&lt;br /&gt;&lt;br /&gt;                 else&lt;br /&gt;&lt;br /&gt;                    // Status event is stored in the event flag&lt;br /&gt;&lt;br /&gt;                    // specified in the original WaitCommEvent call.&lt;br /&gt;&lt;br /&gt;                    // Deal with the status event as appropriate.&lt;br /&gt;&lt;br /&gt;                    ReportStatusEvent(dwCommEvent);&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;                 // Set fWaitingOnStat flag to indicate that a new&lt;br /&gt;&lt;br /&gt;                 // WaitCommEvent is to be issued.&lt;br /&gt;&lt;br /&gt;                 fWaitingOnStat = FALSE;&lt;br /&gt;&lt;br /&gt;                 break;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;             case WAIT_TIMEOUT:&lt;br /&gt;&lt;br /&gt;                 // Operation isn't complete yet. fWaitingOnStatusHandle flag &lt;br /&gt;&lt;br /&gt;                 // isn't changed since I'll loop back around and I don't want&lt;br /&gt;&lt;br /&gt;                 // to issue another WaitCommEvent until the first one finishes.&lt;br /&gt;&lt;br /&gt;                 //&lt;br /&gt;&lt;br /&gt;                 // This is a good time to do some background work.&lt;br /&gt;&lt;br /&gt;                DoBackgroundWork();&lt;br /&gt;&lt;br /&gt;                 break;                       &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;             default:&lt;br /&gt;&lt;br /&gt;                 // Error in the WaitForSingleObject; abort&lt;br /&gt;&lt;br /&gt;                 // This indicates a problem with the OVERLAPPED structure's&lt;br /&gt;&lt;br /&gt;                 // event handle.&lt;br /&gt;&lt;br /&gt;                CloseHandle(osStatus.hEvent);&lt;br /&gt;&lt;br /&gt;                return 0;&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   CloseHandle(osStatus.hEvent);&lt;br /&gt;&lt;br /&gt;The code above very closely resembles the code for overlapped reading. In fact, the MTTTY sample implements its reading and status checking in the same thread using WaitForMultipleObjects to wait for either the read event or the status event to become signaled.&lt;br /&gt;&lt;br /&gt;There are two interesting side effects of SetCommMask and WaitCommEvent. First, if the communications port is open for nonoverlapped operation, WaitCommEvent will be blocked until an event occurs. If another thread calls SetCommMask to set a new event mask, that thread will be blocked on the call to SetCommMask. The reason is that the original call to WaitCommEvent in the first thread is still executing. The call to SetCommMask blocks the thread until the WaitCommEvent function returns in the first thread. This side effect is universal for ports open for nonoverlapped I/O. If a thread is blocked on any communications function and another thread calls a communications function, the second thread is blocked until the communications function returns in the first thread. The second interesting note about these functions is their use on a port open for overlapped operation. If SetCommMask sets a new event mask, any pending WaitCommEvent will complete successfully, and the event mask produced by the operation is NULL.&lt;br /&gt;Caveat&lt;br /&gt;&lt;br /&gt;Using the EV_RXCHAR flag will notify the thread that a byte arrived at the port. This event, used in combination with the ReadFile function, enables a program to read data only after it is in the receive buffer, as opposed to issuing a read that waits for the data to arrive. This is particularly useful when a port is open for nonoverlapped operation because the program does not need to poll for incoming data; the program is notified of the incoming data by the occurrence of the EV_RXCHAR event. Initial attempts to code this solution often produce the following pseudocode, including one oversight covered later in this section:&lt;br /&gt;&lt;br /&gt;DWORD dwCommEvent;&lt;br /&gt;&lt;br /&gt;DWORD dwRead;&lt;br /&gt;&lt;br /&gt;char  chRead;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (!SetCommMask(hComm, EV_RXCHAR))&lt;br /&gt;&lt;br /&gt;   // Error setting communications event mask.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;for ( ; ; ) {&lt;br /&gt;&lt;br /&gt;   if (WaitCommEvent(hComm, &amp;dwCommEvent, NULL)) {&lt;br /&gt;&lt;br /&gt;      if (ReadFile(hComm, &amp;chRead, 1, &amp;dwRead, NULL))&lt;br /&gt;&lt;br /&gt;         // A byte has been read; process it.&lt;br /&gt;&lt;br /&gt;      else&lt;br /&gt;&lt;br /&gt;         // An error occurred in the ReadFile call.&lt;br /&gt;&lt;br /&gt;         break;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // Error in WaitCommEvent.&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The above code waits for an EV_RXCHAR event to occur. When this happens, the code calls ReadFile to read the one byte received. The loop starts again, and the code waits for another EV_RXCHAR event. This code works fine when one or two bytes arrive in quick succession. The byte reception causes the EV_RXCHAR event to occur. The code reads the byte. If no other byte arrives before the code calls WaitCommEvent again, then all is fine; the next byte to arrive will cause the WaitCommEvent function to indicate the occurrence of the EV_RXCHAR event. If another single byte arrives before the code has a chance to reach the WaitCommEvent function, then all is fine, too. The first byte is read as before; the arrival of the second byte causes the EV_RXCHAR flag to be set internally. When the code returns to the WaitCommEvent function, it indicates the occurrence of the EV_RXCHAR event and the second byte is read from the port in the ReadFile call.&lt;br /&gt;&lt;br /&gt;The problem with the above code occurs when three or more bytes arrive in quick succession. The first byte causes the EV_RXCHAR event to occur. The second byte causes the EV_RXCHAR flag to be set internally. The next time the code calls WaitCommEvent, it indicates the EV_RXCHAR event. Now, a third byte arrives at the communications port. This third byte causes the system to attempt to set the EV_RXCHAR flag internally. Because this has already occurred when the second byte arrived, the arrival of the third byte goes unnoticed. The code eventually will read the first byte without a problem. After this, the code will call WaitCommEvent, and it indicates the occurrence of the EV_RXCHAR event (from the arrival of the second byte). The second byte is read, and the code returns to the WaitCommEvent function. The third byte waits in the system’s internal receive buffer. The code and the system are now out of sync. When a fourth byte finally arrives, the EV_RXCHAR event occurs, and the code reads a single byte. It reads the third byte. This will continue indefinitely.&lt;br /&gt;&lt;br /&gt;The solution to this problem seems as easy as increasing the number of bytes requested in the read operation. Instead of requesting a single byte, the code could request two, ten, or some other number of bytes. The problem with this idea is that it still fails when two or more extra bytes above the size of the read request arrive at the port in quick succession. So, if two bytes are read, then four bytes arriving in quick succession would cause the problem. Ten bytes requested would still fail if twelve bytes arrived in quick succession.&lt;br /&gt;&lt;br /&gt;The real solution to this problem is to read from the port until no bytes are remaining. The following pseudocode solves the problem by reading in a loop until zero characters are read. Another possible method would be to call ClearCommError to determine the number of bytes in the buffer and read them all in one read operation. This method requires more sophisticated buffer management, but it reduces the number of reads when a lot of data arrives at once.&lt;br /&gt;&lt;br /&gt;DWORD dwCommEvent;&lt;br /&gt;&lt;br /&gt;DWORD dwRead;&lt;br /&gt;&lt;br /&gt;char  chRead;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (!SetCommMask(hComm, EV_RXCHAR))&lt;br /&gt;&lt;br /&gt;   // Error setting communications event mask&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;for ( ; ; ) {&lt;br /&gt;&lt;br /&gt;   if (WaitCommEvent(hComm, &amp;dwCommEvent, NULL)) {&lt;br /&gt;&lt;br /&gt;      do {&lt;br /&gt;&lt;br /&gt;         if (ReadFile(hComm, &amp;chRead, 1, &amp;dwRead, NULL))&lt;br /&gt;&lt;br /&gt;            // A byte has been read; process it.&lt;br /&gt;&lt;br /&gt;         else&lt;br /&gt;&lt;br /&gt;            // An error occurred in the ReadFile call.&lt;br /&gt;&lt;br /&gt;            break;&lt;br /&gt;&lt;br /&gt;      } while (dwRead);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // Error in WaitCommEvent&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The above code does not work correctly without setting the proper time-outs. Communications time-outs, discussed later, affect the behavior of the ReadFile operation in order to cause it to return without waiting for bytes to arrive. Discussion of this topic occurs later in the “Communications Time-outs?section of this article.&lt;br /&gt;&lt;br /&gt;The above caveat regarding EV_RXCHAR also applies to EV_RXFLAG. If flag characters arrive in quick succession, EV_RXFLAG events may not occur for all of them. Once again, the best solution is to read all bytes until none remain.&lt;br /&gt;&lt;br /&gt;The above caveat also applies to other events not related to character reception. If other events occur in quick succession some of the notifications will be lost. For instance, if the CTS line voltage starts high, then goes low, high, and low again, an EV_CTS event occurs. There is no guarantee of how many EV_CTS events will actually be detected with WaitCommEvent if the changes in the CTS line happen quickly. For this reason, WaitCommEvent cannot be used to keep track of the state of the line. Line status is covered in the “Modem Status?section later in this article.&lt;br /&gt;Error Handling and Communications Status&lt;br /&gt;&lt;br /&gt;One of the communications event flags specified in the call to SetCommMask is possibly EV_ERR. The occurrence of the EV_ERR event indicates that an error condition exists in the communications port. Other errors can occur in the port that do not cause the EV_ERR event to occur. In either case, errors associated with the communications port cause all I/O operations to be suspended until removal of the error condition. ClearCommError is the function to call to detect errors and clear the error condition.&lt;br /&gt;&lt;br /&gt;ClearCommError also provides communications status indicating why transmission has stopped; it also indicates the number of bytes waiting in the transmit and receive buffers. The reason why transmission may stop is because of errors or to flow control. The discussion of flow control occurs later in this article.&lt;br /&gt;&lt;br /&gt;Here is some code that demonstrates how to call ClearCommError:&lt;br /&gt;&lt;br /&gt;    COMSTAT comStat;&lt;br /&gt;&lt;br /&gt;    DWORD   dwErrors;&lt;br /&gt;&lt;br /&gt;    BOOL    fOOP, fOVERRUN, fPTO, fRXOVER, fRXPARITY, fTXFULL;&lt;br /&gt;&lt;br /&gt;    BOOL    fBREAK, fDNS, fFRAME, fIOE, fMODE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    // Get and clear current errors on the port.&lt;br /&gt;&lt;br /&gt;    if (!ClearCommError(hComm, &amp;dwErrors, &amp;comStat))&lt;br /&gt;&lt;br /&gt;        // Report error in ClearCommError.&lt;br /&gt;&lt;br /&gt;        return;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    // Get error flags.&lt;br /&gt;&lt;br /&gt;    fDNS = dwErrors &amp; CE_DNS;&lt;br /&gt;&lt;br /&gt;    fIOE = dwErrors &amp; CE_IOE;&lt;br /&gt;&lt;br /&gt;    fOOP = dwErrors &amp; CE_OOP;&lt;br /&gt;&lt;br /&gt;    fPTO = dwErrors &amp; CE_PTO;&lt;br /&gt;&lt;br /&gt;    fMODE = dwErrors &amp; CE_MODE;&lt;br /&gt;&lt;br /&gt;    fBREAK = dwErrors &amp; CE_BREAK;&lt;br /&gt;&lt;br /&gt;    fFRAME = dwErrors &amp; CE_FRAME;&lt;br /&gt;&lt;br /&gt;    fRXOVER = dwErrors &amp; CE_RXOVER;&lt;br /&gt;&lt;br /&gt;    fTXFULL = dwErrors &amp; CE_TXFULL;&lt;br /&gt;&lt;br /&gt;    fOVERRUN = dwErrors &amp; CE_OVERRUN;&lt;br /&gt;&lt;br /&gt;    fRXPARITY = dwErrors &amp; CE_RXPARITY;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    // COMSTAT structure contains information regarding&lt;br /&gt;&lt;br /&gt;    // communications status.&lt;br /&gt;&lt;br /&gt;    if (comStat.fCtsHold)&lt;br /&gt;&lt;br /&gt;        // Tx waiting for CTS signal&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.fDsrHold)&lt;br /&gt;&lt;br /&gt;        // Tx waiting for DSR signal&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.fRlsdHold)&lt;br /&gt;&lt;br /&gt;        // Tx waiting for RLSD signal&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.fXoffHold)&lt;br /&gt;&lt;br /&gt;        // Tx waiting, XOFF char rec'd&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.fXoffSent)&lt;br /&gt;&lt;br /&gt;        // Tx waiting, XOFF char sent&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    if (comStat.fEof)&lt;br /&gt;&lt;br /&gt;        // EOF character received&lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    if (comStat.fTxim)&lt;br /&gt;&lt;br /&gt;        // Character waiting for Tx; char queued with TransmitCommChar&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.cbInQue)&lt;br /&gt;&lt;br /&gt;        // comStat.cbInQue bytes have been received, but not read&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    if (comStat.cbOutQue)&lt;br /&gt;&lt;br /&gt;        // comStat.cbOutQue bytes are awaiting transfer&lt;br /&gt;&lt;br /&gt;Modem Status (a.k.a. Line Status)&lt;br /&gt;&lt;br /&gt;The call to SetCommMask may include the flags EV_CTS, EV_DSR, EV_RING, and EV_RLSD. These flags indicate changes in the voltage on the lines of the serial port. There is no indication of the actual status of these lines, just that a change occurred. The GetCommModemStatus function retrieves the actual state of these status lines by returning a bit mask indicating a 0 for low or no voltage and 1 for high voltage for each of the lines.&lt;br /&gt;&lt;br /&gt;Please note that the term RLSD (Receive Line Signal Detect) is commonly referred to as the CD (Carrier Detect) line.&lt;br /&gt;&lt;br /&gt;Note   The EV_RING flag does not work in Windows 95 as mentioned earlier. The GetCommModemStatus function, however, does detect the state of the RING line.&lt;br /&gt;&lt;br /&gt;Changes in these lines may also cause a flow-control event. The ClearCommError function reports whether transmission is suspended because of flow control. If necessary, a thread may call ClearCommError to detect whether the event is the cause of a flow-control action. Flow control is covered in the “Flow Control?section later in this article.&lt;br /&gt;&lt;br /&gt;Here is some code that demonstrates how to call GetCommModemStatus:&lt;br /&gt;&lt;br /&gt;   DWORD dwModemStatus;&lt;br /&gt;&lt;br /&gt;   BOOL  fCTS, fDSR, fRING, fRLSD;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   if (!GetCommModemStatus(hComm, &amp;dwModemStatus))&lt;br /&gt;&lt;br /&gt;      // Error in GetCommModemStatus;&lt;br /&gt;&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   fCTS = MS_CTS_ON &amp; dwModemStatus;&lt;br /&gt;&lt;br /&gt;   fDSR = MS_DSR_ON &amp; dwModemStatus;&lt;br /&gt;&lt;br /&gt;   fRING = MS_RING_ON &amp; dwModemStatus;&lt;br /&gt;&lt;br /&gt;   fRLSD = MS_RLSD_ON &amp; dwModemStatus;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Do something with the flags.&lt;br /&gt;&lt;br /&gt;Extended Functions&lt;br /&gt;&lt;br /&gt;The driver will automatically change the state of control lines as necessary. Generally speaking, changing status lines is under the control of a driver. If a device uses communications port control lines in a manner different from RS-232 standards, the standard serial communications driver will not work to control the device. If the standard serial communications driver will not control the device, a custom device driver is necessary.&lt;br /&gt;&lt;br /&gt;There are occasions when standard control lines are under the control of the application instead of the serial communications driver. For instance, an application may wish to implement its own flow control. The application would be responsible for changing the status of the RTS and DTR lines. EscapeCommFunction directs a communications driver to perform such extended operations. EscapeCommFunction can make the driver perform some other function, such as setting or clearing a BREAK condition. For more information on this function, consult the Platform SDK documentation, the Microsoft Win32 SDK Knowledge Base, or the Microsoft Developer Network (MSDN) Library.&lt;br /&gt;Serial Settings&lt;br /&gt;DCB Settings&lt;br /&gt;&lt;br /&gt;The most crucial aspect of programming serial communications applications is the settings in the Device-Control Block (DCB) structure. The most common errors in serial communications programming occur in initializing the DCB structure improperly. When the serial communications functions do not behave as expected, a close examination of the DCB structure usually reveals the problem.&lt;br /&gt;&lt;br /&gt;There are three ways to initialize a DCB structure. The first method is to use the function GetCommState. This function returns the current DCB in use for the communications port. The following code shows how to use the GetCommState function:&lt;br /&gt;&lt;br /&gt;   DCB dcb = {0};&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   if (!GetCommState(hComm, &amp;dcb))&lt;br /&gt;&lt;br /&gt;      // Error getting current DCB settings&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // DCB is ready for use.&lt;br /&gt;&lt;br /&gt;The second method to initialize a DCB is to use a function called BuildCommDCB. This function fills in the baud, parity type, number of stop bits, and number of data bits members of the DCB. The function also sets the flow-control members to default values. Consult the documentation of the BuildCommDCB function for details on which default values it uses for flow-control members. Other members of the DCB are unaffected by this function. It is the program's duty to make sure the other members of the DCB do not cause errors. The simplest thing to do in this regard is to initialize the DCB structure with zeros and then set the size member to the size, in bytes, of the structure. If the zero initialization of the DCB structure does not occur, then there may be nonzero values in the reserved members; this produces an error when trying to use the DCB later. The following function shows how to properly use this method:&lt;br /&gt;&lt;br /&gt;   DCB dcb;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   FillMemory(&amp;dcb, sizeof(dcb), 0);&lt;br /&gt;&lt;br /&gt;   dcb.DCBlength = sizeof(dcb);&lt;br /&gt;&lt;br /&gt;   if (!BuildCommDCB("9600,n,8,1", &amp;dcb)) {   &lt;br /&gt;&lt;br /&gt;      // Couldn't build the DCB. Usually a problem&lt;br /&gt;&lt;br /&gt;      // with the communications specification string.&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else&lt;br /&gt;&lt;br /&gt;      // DCB is ready for use.&lt;br /&gt;&lt;br /&gt;The third method to initialize a DCB structure is to do it manually. The program allocates the DCB structure and sets each member with any value desired. This method does not deal well with changes to the DCB in future implementations of Win32 and is not recommended.&lt;br /&gt;&lt;br /&gt;An application usually needs to set some of the DCB members differently than the defaults or may need to modify settings in the middle of execution. Once proper initialization of the DCB occurs, modification of individual members is possible. The changes to the DCB structure do not have any effect on the behavior of the port until execution of the SetCommState function. Here is a section of code that retrieves the current DCB, changes the baud, and then attempts to set the configuration:&lt;br /&gt;&lt;br /&gt;   DCB dcb;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   FillMemory(&amp;dcb, sizeof(dcb), 0);&lt;br /&gt;&lt;br /&gt;   if (!GetCommState(hComm, &amp;dcb))     // get current DCB&lt;br /&gt;&lt;br /&gt;      // Error in GetCommState&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Update DCB rate.&lt;br /&gt;&lt;br /&gt;   dcb.BaudRate = CBR_9600 ;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Set new state.&lt;br /&gt;&lt;br /&gt;   if (!SetCommState(hComm, &amp;dcb))&lt;br /&gt;&lt;br /&gt;      // Error in SetCommState. Possibly a problem with the communications &lt;br /&gt;&lt;br /&gt;      // port handle or a problem with the DCB structure itself.&lt;br /&gt;&lt;br /&gt;Here is an explanation of each of the members of the DCB and how they affect other parts of the serial communications functions.&lt;br /&gt;&lt;br /&gt;Note   Most of this information is from the Platform SDK documentation. Because documentation is the official word in what the members actually are and what they mean, this table may not be completely accurate if changes occur in the operating system.&lt;br /&gt;&lt;br /&gt;Table 2. The DCB Structure Members&lt;br /&gt;&lt;br /&gt;Member&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Description&lt;br /&gt;&lt;br /&gt;DCBlength&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Size, in bytes, of the structure. Should be set before calling SetCommState to update the settings.&lt;br /&gt;&lt;br /&gt;BaudRate&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the baud at which the communications device operates. This member can be an actual baud value, or a baud index.&lt;br /&gt;&lt;br /&gt;fBinary&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether binary mode is enabled. The Win32 API does not support nonbinary mode transfers, so this member should be TRUE. Trying to use FALSE will not work.&lt;br /&gt;&lt;br /&gt;fParity&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether parity checking is enabled. If this member is TRUE, parity checking is performed and parity errors are reported. This should not be confused with the Parity member, which controls the type of parity used in communications.&lt;br /&gt;&lt;br /&gt;fOutxCtsFlow&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether the CTS (clear-to-send) signal is monitored for output flow control. If this member is TRUE and CTS is low, output is suspended until CTS is high again. The CTS signal is under control of the DCE (usually a modem), the DTE (usually the PC) simply monitors the status of this signal, the DTE does not change it.&lt;br /&gt;&lt;br /&gt;fOutxDsrFlow&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether the DSR (data-set-ready) signal is monitored for output flow control. If this member is TRUE and DSR is low, output is suspended until DSR is high again. Once again, this signal is under the control of the DCE; the DTE only monitors this signal.&lt;br /&gt;&lt;br /&gt;fDtrControl&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the DTR (data-terminal-ready) input flow control. This member can be one of the following values:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Value&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Meaning&lt;br /&gt;&lt;br /&gt;DTR_CONTROL_DISABLE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Lowers the DTR line when the device is opened. The application can adjust the state of the line with EscapeCommFunction.&lt;br /&gt;&lt;br /&gt;DTR_CONTROL_ENABLE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Raises the DTR line when the device is opened. The application can adjust the state of the line with EscapeCommFunction.&lt;br /&gt;&lt;br /&gt;DTR_CONTROL_HANDSHAKE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Enables DTR flow-control handshaking. If this value is used, it is an error for the application to adjust the line with EscapeCommFunction.&lt;br /&gt;&lt;br /&gt;fDsrSensitivity&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether the communications driver is sensitive to the state of the DSR signal. If this member is TRUE, the driver ignores any bytes received, unless the DSR modem input line is high.&lt;br /&gt;&lt;br /&gt;fTXContinueOnXoff&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether transmission stops when the input buffer is full and the driver has transmitted the XOFF character. If this member is TRUE, transmission continues after the XOFF character has been sent. If this member is FALSE, transmission does not continue until the input buffer is within XonLim bytes of being empty and the driver has transmitted the XON character.&lt;br /&gt;&lt;br /&gt;fOutX&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether XON/XOFF flow control is used during transmission. If this member is TRUE, transmission stops when the XOFF character is received and starts again when the XON character is received.&lt;br /&gt;&lt;br /&gt;fInX&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether XON/XOFF flow control is used during reception. If this member is TRUE, the XOFF character is sent when the input buffer comes within XoffLim bytes of being full, and the XON character is sent when the input buffer comes within XonLim bytes of being empty.&lt;br /&gt;&lt;br /&gt;fErrorChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether bytes received with parity errors are replaced with the character specified by the ErrorChar member. If this member is TRUE and the fParity member is TRUE, replacement occurs.&lt;br /&gt;&lt;br /&gt;fNull&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether null bytes are discarded. If this member is TRUE, null bytes are discarded when received.&lt;br /&gt;&lt;br /&gt;fRtsControl&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the RTS (request-to-send) input flow control. If this value is zero, the default is RTS_CONTROL_HANDSHAKE. This member can be one of the following values:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Value&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Meaning&lt;br /&gt;&lt;br /&gt;RTS_CONTROL_DISABLE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Lowers the RTS line when the device is opened. The application can use EscapeCommFunction to change the state of the line.&lt;br /&gt;&lt;br /&gt;RTS_CONTROL_ENABLE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Raises the RTS line when the device is opened. The application can use EscapeCommFunction to change the state of the line.&lt;br /&gt;&lt;br /&gt;RTS_CONTROL_HANDSHAKE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Enables RTS flow-control handshaking. The driver raises the RTS line, enabling the DCE to send, when the input buffer has enough room to receive data. The driver lowers the RTS line, preventing the DCE to send, when the input buffer does not have enough room to receive data. If this value is used, it is an error for the application to adjust the line with EscapeCommFunction.&lt;br /&gt;&lt;br /&gt;RTS_CONTROL_TOGGLE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies that the RTS line will be high if bytes are available for transmission. After all buffered bytes have been sent, the RTS line will be low. If this value is set, it would be an error for an application to adjust the line with EscapeCommFunction. This value is ignored in Windows 95; it causes the driver to act as if RTS_CONTROL_ENABLE were specified.&lt;br /&gt;&lt;br /&gt;fAbortOnError&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies whether read and write operations are terminated if an error occurs. If this member is TRUE, the driver terminates all read and write operations with an error status (ERROR_IO_ABORTED) if an error occurs. The driver will not accept any further communications operations until the application has acknowledged the error by calling the ClearCommError function.&lt;br /&gt;&lt;br /&gt;fDummy2&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Reserved; do not use.&lt;br /&gt;&lt;br /&gt;wReserved&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Not used; must be set to zero.&lt;br /&gt;&lt;br /&gt;XonLim&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the minimum number of bytes allowed in the input buffer before the XON character is sent.&lt;br /&gt;&lt;br /&gt;XoffLim&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the maximum number of bytes allowed in the input buffer before the XOFF character is sent. The maximum number of bytes allowed is calculated by subtracting this value from the size, in bytes, of the input buffer.&lt;br /&gt;&lt;br /&gt;Parity&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the parity scheme to be used. This member can be one of the following values:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Value&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Meaning&lt;br /&gt;&lt;br /&gt;EVENPARITY&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Even&lt;br /&gt;&lt;br /&gt;MARKPARITY&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Mark&lt;br /&gt;&lt;br /&gt;NOPARITY&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;No parity&lt;br /&gt;&lt;br /&gt;ODDPARITY&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Odd&lt;br /&gt;&lt;br /&gt;StopBits&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the number of stop bits to be used. This member can be one of the following values:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Value&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Meaning&lt;br /&gt;&lt;br /&gt;ONESTOPBIT&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;1 stop bit&lt;br /&gt;&lt;br /&gt;ONE5STOPBITS&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;1.5 stop bits&lt;br /&gt;&lt;br /&gt;TWOSTOPBITS&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;2 stop bits&lt;br /&gt;&lt;br /&gt;XonChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the value of the XON character for both transmission and reception.&lt;br /&gt;&lt;br /&gt;XoffChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the value of the XOFF character for both transmission and reception.&lt;br /&gt;&lt;br /&gt;ErrorChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the value of the character used to replace bytes received with a parity error.&lt;br /&gt;&lt;br /&gt;EofChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the value of the character used to signal the end of data.&lt;br /&gt;&lt;br /&gt;EvtChar&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Specifies the value of the character used to cause the EV_RXFLAG event. This setting does not actually cause anything to happen without the use of EV_RXFLAG in the SetCommMask function and the use of WaitCommEvent.&lt;br /&gt;&lt;br /&gt;wReserved1&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Reserved; do not use.&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;Flow Control&lt;br /&gt;&lt;br /&gt;Flow control in serial communications provides a mechanism for suspending communications while one of the devices is busy or for some reason cannot do any communication. There are traditionally two types of flow control: hardware and software.&lt;br /&gt;&lt;br /&gt;A common problem with serial communications is write operations that actually do not write the data to the device. Often, the problem lies in flow control being used when the program did not specify it. A close examination of the DCB structure reveals that one or more of the following members may be TRUE: fOutxCtsFlow, fOutxDsrFlow, or fOutX. Another mechanism to reveal that flow control is enabled is to call ClearCommError and examine the COMSTAT structure. It will reveal when transmission is suspended because of flow control.&lt;br /&gt;&lt;br /&gt;Before discussing the types of flow control, a good understanding of some terms is in order. Serial communications takes place between two devices. Traditionally, there is a PC and a modem or printer. The PC is labeled the Data Terminal Equipment (DTE). The DTE is sometimes called the host. The modem, printer, or other peripheral equipment is identified as the Data Communications Equipment (DCE). The DCE is sometimes referred to as the device.&lt;br /&gt;Hardware flow control&lt;br /&gt;&lt;br /&gt;Hardware flow control uses voltage signals on control lines of the serial cable to control whether sending or receiving is enabled. The DTE and the DCE must agree on the types of flow control used for a communications session. Setting the DCB structure to enable flow control just configures the DTE. The DCE also needs configuration to make certain the DTE and DCE use the same type of flow control. There is no mechanism provided by Win32 to set the flow control of the DCE. DIP switches on the device, or commands sent to it typically establish its configuration. The following table describes the control lines, the direction of the flow control, and the line's effect on the DTE and DCE.&lt;br /&gt;&lt;br /&gt;Table 3. Hardware Flow-control Lines&lt;br /&gt;&lt;br /&gt;Line and Direction&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Effect on DTE/DCE&lt;br /&gt;&lt;br /&gt;CTS&lt;br /&gt;(Clear To Send)&lt;br /&gt;Output flow control&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;DCE sets the line high to indicate that it can receive data. DCE sets the line low to indicate that it cannot receive data.&lt;br /&gt;&lt;br /&gt;If the fOutxCtsFlow member of the DCB is TRUE, then the DTE will not send data if this line is low. It will resume sending if the line is high.&lt;br /&gt;&lt;br /&gt;If the fOutxCtsFlow member of the DCB is FALSE, then the state of the line does not affect transmission.&lt;br /&gt;&lt;br /&gt;DSR&lt;br /&gt;(Data Set Ready)&lt;br /&gt;Output flow control&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;DCE sets the line high to indicate that it can receive data. DCE sets the line low to indicate that it cannot receive data.&lt;br /&gt;&lt;br /&gt;If the fOutxDsrFlow member of the DCB is TRUE, then the DTE will not send data if this line is low. It will resume sending if the line is high.&lt;br /&gt;&lt;br /&gt;If the fOutxDsrFlow member of the DCB is FALSE, then the state of the line does not affect transmission.&lt;br /&gt;&lt;br /&gt;DSR&lt;br /&gt;(Data Set Ready)&lt;br /&gt;Input flow control&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;If the DSR line is low, then data that arrives at the port is ignored. If the DSR line is high, data that arrives at the port is received.&lt;br /&gt;&lt;br /&gt;This behavior occurs if the fDsrSensitivity member of the DCB is set to TRUE. If it is FALSE, then the state of the line does not affect reception.&lt;br /&gt;&lt;br /&gt;RTS&lt;br /&gt;(Ready To Send)&lt;br /&gt;Input flow control&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The RTS line is controlled by the DTE.&lt;br /&gt;&lt;br /&gt;If the fRtsControl member of the DCB is set to RTS_CONTROL_HANDSHAKE, the following flow control is used: If the input buffer has enough room to receive data (at least half the buffer is empty), the driver sets the RTS line high. If the input buffer has little room for incoming data (less than a quarter of the buffer is empty), the driver sets the RTS line low.&lt;br /&gt;&lt;br /&gt;If the fRtsControl member of the DCB is set to RTS_CONTROL_TOGGLE, the driver sets the RTS line high when data is available for sending. The driver sets the line low when no data is available for sending. Windows 95 ignores this value and treats it the same as RTS_CONTROL_ENABLE.&lt;br /&gt;&lt;br /&gt;If the fRtsControl member of the DCB is set to RTS_CONTROL_ENABLE or RTS_CONTROL_DISABLE, the application is free to change the state of the line as it needs. Note that in this case, the state of the line does not affect reception.&lt;br /&gt;&lt;br /&gt;The DCE will suspend transmission when the line goes low. The DCE will resume transmission when the line goes high.&lt;br /&gt;&lt;br /&gt;DTR&lt;br /&gt;(Data Terminal Ready)&lt;br /&gt;Input flow control&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The DTR line is controlled by the DTE.&lt;br /&gt;&lt;br /&gt;If the fDtrControl member of the DCB is set to DTR_CONTROL_HANDSHAKE, the following flow control is used: If the input buffer has enough room to receive data (at least half the buffer is empty), the driver sets the DTR line high. If the input buffer has little room for incoming data (less than a quarter of the buffer is empty), the driver sets the DTR line low.&lt;br /&gt;&lt;br /&gt;If the fDtrControl member of the DCB is set to DTR_CONTROL_ENABLE or DTR_CONTROL_DISABLE, the application is free to change the state of the line as it needs. In this case, the state of the line does not affect reception.&lt;br /&gt;&lt;br /&gt;The DCE will suspend transmission when the line goes low. The DCE will resume transmission when the line goes high.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;The need for flow control is easy to recognize when the CE_RXOVER error occurs. This error indicates an overflow of the receive buffer and data loss. If data arrives at the port faster than it is read, CE_RXOVER can occur. Increasing the input buffer size may cause the error to occur less frequently, but it does not completely solve the problem. Input flow control is necessary to completely alleviate this problem. When the driver detects that the input buffer is nearly full, it will lower the input flow-control lines. This should cause the DCE to stop transmitting, which gives the DTE enough time to read the data from the input buffer. When the input buffer has more room available, the voltage on flow-control lines is set high, and the DCE resumes sending data.&lt;br /&gt;&lt;br /&gt;A similar error is CE_OVERRUN. This error occurs when new data arrives before the communications hardware and serial communications driver completely receives old data. This can occur when the transmission speed is too high for the type of communications hardware or CPU. This can also occur when the operating system is not free to service the communications hardware. The only way to alleviate this problem is to apply some combination of decreasing the transmission speed, replacing the communications hardware, and increasing the CPU speed. Sometimes third-party hardware drivers that are not very efficient with CPU resources cause this error. Flow control cannot completely solve the problems that cause the CE_OVERRUN error, although it may help to reduce the frequency of the error.&lt;br /&gt;Software flow control&lt;br /&gt;&lt;br /&gt;Software flow control uses data in the communications stream to control the transmission and reception of data. Because software flow control uses two special characters, XOFF and XON, binary transfers cannot use software flow control; the XON or XOFF character may appear in the binary data and would interfere with data transfer. Software flow control befits text-based communications or data being transferred that does not contain the XON and XOFF characters.&lt;br /&gt;&lt;br /&gt;In order to enable software flow control, the fOutX and fInX members of the DCB must be set to TRUE. The fOutX member controls output flow control. The fInX member controls input flow control.&lt;br /&gt;&lt;br /&gt;One thing to note is that the DCB allows the program to dynamically assign the values the system recognizes as flow-control characters. The XoffChar member of the DCB dictates the XOFF character for both input and output flow control. The XonChar member of the DCB similarly dictates the XON character.&lt;br /&gt;&lt;br /&gt;For input flow control, the XoffLim member of the DCB specifies the minimum amount of free space allowed in the input buffer before the XOFF character is sent. If the amount of free space in the input buffer drops below this amount, then the XOFF character is sent. For input flow control, the XonLim member of the DCB specifies the minimum number of bytes allowed in the input buffer before the XON character is sent. If the amount of data in the input buffer drops below this value, then the XON character is sent.&lt;br /&gt;&lt;br /&gt;Table 4 lists the behavior of the DTE when using XOFF/XON flow control.&lt;br /&gt;&lt;br /&gt;Table 4. Software flow-control behavior&lt;br /&gt;&lt;br /&gt;Flow-control character&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Behavior&lt;br /&gt;&lt;br /&gt;XOFF received by DTE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;DTE transmission is suspended until XON is received. DTE reception continues. The fOutX member of the DCB controls this behavior.&lt;br /&gt;&lt;br /&gt;XON received by DTE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;If DTE transmission is suspended because of a previous XOFF character being received, DTE transmission is resumed. The fOutX member of the DCB controls this behavior.&lt;br /&gt;&lt;br /&gt;XOFF sent from DTE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;XOFF is automatically sent by the DTE when the receive buffer approaches full. The actual limit is dictated by the XoffLim member of the DCB. The fInX member of the DCB controls this behavior. DTE transmission is controlled by the fTXContinueOnXoff member of the DCB as described below.&lt;br /&gt;&lt;br /&gt;XON sent from the DTE&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;XON is automatically sent by the DTE when the receive buffer approaches empty. The actual limit is dictated by the XonLim member of the DCB. The fInX member of the DCB controls this behavior.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;If software flow control is enabled for input control, then the fTXContinueOnXoff member of the DCB takes effect. The fTXContinueOnXoff member controls whether transmission is suspended after the XOFF character is automatically sent by the system. If fTXContinueOnXoff is TRUE, then transmission continues after the XOFF is sent when the receive buffer is full. If fTXContinueOnXoff is FALSE, then transmission is suspended until the system automatically sends the XON character. DCE devices using software flow control will suspend their sending after the XOFF character is received. Some equipment will resume sending when the XON character is sent by the DTE. On the other hand, some DCE devices will resume sending after any character arrives. The fTXContinueOnXoff member should be set to FALSE when communicating with a DCE device that resumes sending after any character arrives. If the DTE continued transmission after it automatically sent the XOFF, the resumption of transmission would cause the DCE to continue sending, defeating the XOFF.&lt;br /&gt;&lt;br /&gt;There is no mechanism available in the Win32 API to cause the DTE to behave the same way as these devices. The DCB structure contains no members for specifying suspended transmission to resume when any character is received. The XON character is the only character that causes transmission to resume.&lt;br /&gt;&lt;br /&gt;One other interesting note about software flow control is that reception of XON and XOFF characters causes pending read operations to complete with zero bytes read. The XON and XOFF characters cannot be read by the application, since they are not placed in the input buffer.&lt;br /&gt;&lt;br /&gt;A lot of programs on the market, including the Terminal program that comes with Windows, give the user three choices for flow control: Hardware, Software, or None. The Windows operating system itself does not limit an application in this way. The settings of the DCB allow for Software and Hardware flow control simultaneously. In fact, it is possible to separately configure each member of the DCB that affects flow control, which allows for several different flow-control configurations. The limits placed on flow-control choices are there for ease-of-use reasons to reduce confusion for end users. The limits placed on flow-control choices may also be because devices used for communications may not support all types of flow control.&lt;br /&gt;Communications Time-outs&lt;br /&gt;&lt;br /&gt;Another major topic affecting the behavior of read and write operations is time-outs. Time-outs affect read and write operations in the following way. If an operation takes longer than the computed time-out period, the operation is completed. There is no error code that is returned by ReadFile, WriteFile, GetOverlappedResult, or WaitForSingleObject. All indicators used to monitor the operation indicate that it completed successfully. The only way to tell that the operation timed out is that the number of bytes actually transferred are fewer than the number of bytes requested. So, if ReadFile returns TRUE, but fewer bytes were read than were requested, the operation timed out. If an overlapped write operation times out, the overlapped event handle is signaled and WaitForSingleObject returns WAIT_OBJECT_O. GetOverlappedResult returns TRUE, but dwBytesTransferred contains the number of bytes that were transferred before the time-out. The following code demonstrates how to handle this in an overlapped write operation:&lt;br /&gt;&lt;br /&gt;BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   OVERLAPPED osWrite = {0};&lt;br /&gt;&lt;br /&gt;   DWORD dwWritten;&lt;br /&gt;&lt;br /&gt;   DWORD dwRes;&lt;br /&gt;&lt;br /&gt;   BOOL  fRes;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Create this write operation's OVERLAPPED structure hEvent.&lt;br /&gt;&lt;br /&gt;   osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);&lt;br /&gt;&lt;br /&gt;   if (osWrite.hEvent == NULL)&lt;br /&gt;&lt;br /&gt;      // Error creating overlapped event handle.&lt;br /&gt;&lt;br /&gt;      return FALSE;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   // Issue write&lt;br /&gt;&lt;br /&gt;   if (!WriteFile(hComm, lpBuf, dwToWrite, &amp;dwWritten, &amp;osWrite)) {&lt;br /&gt;&lt;br /&gt;      if (GetLastError() != ERROR_IO_PENDING) { &lt;br /&gt;&lt;br /&gt;         // WriteFile failed, but it isn't delayed. Report error.&lt;br /&gt;&lt;br /&gt;         fRes = FALSE;&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      else&lt;br /&gt;&lt;br /&gt;         // Write is pending.&lt;br /&gt;&lt;br /&gt;         dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);&lt;br /&gt;&lt;br /&gt;         switch(dwRes)&lt;br /&gt;&lt;br /&gt;         {&lt;br /&gt;&lt;br /&gt;            // Overlapped event has been signaled. &lt;br /&gt;&lt;br /&gt;            case WAIT_OBJECT_0:&lt;br /&gt;&lt;br /&gt;                 if (!GetOverlappedResult(hComm, &amp;osWrite, &amp;dwWritten, FALSE))&lt;br /&gt;&lt;br /&gt;                       fRes = FALSE;&lt;br /&gt;&lt;br /&gt;                 else {&lt;br /&gt;&lt;br /&gt;                  if (dwWritten != dwToWrite) {&lt;br /&gt;&lt;br /&gt;                     // The write operation timed out. I now need to &lt;br /&gt;&lt;br /&gt;                     // decide if I want to abort or retry. If I retry, &lt;br /&gt;&lt;br /&gt;                     // I need to send only the bytes that weren't sent. &lt;br /&gt;&lt;br /&gt;                     // If I want to abort, I would just set fRes to &lt;br /&gt;&lt;br /&gt;                     // FALSE and return.&lt;br /&gt;&lt;br /&gt;                     fRes = FALSE;&lt;br /&gt;&lt;br /&gt;                  }&lt;br /&gt;&lt;br /&gt;                  else&lt;br /&gt;&lt;br /&gt;                     // Write operation completed successfully.&lt;br /&gt;&lt;br /&gt;                     fRes = TRUE;&lt;br /&gt;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                 break;&lt;br /&gt;&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;            default:&lt;br /&gt;&lt;br /&gt;                 // An error has occurred in WaitForSingleObject. This usually &lt;br /&gt;&lt;br /&gt;                // indicates a problem with the overlapped event handle.&lt;br /&gt;&lt;br /&gt;                 fRes = FALSE;&lt;br /&gt;&lt;br /&gt;                 break;&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   else {&lt;br /&gt;&lt;br /&gt;      // WriteFile completed immediately.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;      if (dwWritten != dwToWrite) {&lt;br /&gt;&lt;br /&gt;          // The write operation timed out. I now need to &lt;br /&gt;&lt;br /&gt;          // decide if I want to abort or retry. If I retry, &lt;br /&gt;&lt;br /&gt;          // I need to send only the bytes that weren't sent. &lt;br /&gt;&lt;br /&gt;          // If I want to abort, then I would just set fRes to &lt;br /&gt;&lt;br /&gt;          // FALSE and return.&lt;br /&gt;&lt;br /&gt;          fRes = FALSE;&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      else&lt;br /&gt;&lt;br /&gt;          fRes = TRUE;&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;   CloseHandle(osWrite.hEvent);&lt;br /&gt;&lt;br /&gt;   return fRes;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The SetCommTimeouts function specifies the communications time-outs for a port. To retrieve the current time-outs for a port, a program calls the GetCommTimeouts function. An applications should retrieve the communications time-outs before modifying them. This allows the application to set time-outs back to their original settings when it finishes with the port. Following is an example of setting new time-outs using SetCommTimeouts:&lt;br /&gt;&lt;br /&gt;COMMTIMEOUTS timeouts;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;timeouts.ReadIntervalTimeout = 20; &lt;br /&gt;&lt;br /&gt;timeouts.ReadTotalTimeoutMultiplier = 10;&lt;br /&gt;&lt;br /&gt;timeouts.ReadTotalTimeoutConstant = 100;&lt;br /&gt;&lt;br /&gt;timeouts.WriteTotalTimeoutMultiplier = 10;&lt;br /&gt;&lt;br /&gt;timeouts.WriteTotalTimeoutConstant = 100;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (!SetCommTimeouts(hComm, &amp;timeouts))&lt;br /&gt;&lt;br /&gt;   // Error setting time-outs.&lt;br /&gt;&lt;br /&gt;Note   Once again, communications time-outs are not the same as time-out values supplied in synchronization functions. WaitForSingleObject, for instance, uses a time-out value to wait for an object to become signaled; this is not the same as a communications time-out.&lt;br /&gt;&lt;br /&gt;Setting the members of the COMMTIMEOUTS structure to all zeros causes no time-outs to occur. Nonoverlapped operations will block until all the requested bytes are transferred. The ReadFile function is blocked until all the requested characters arrive at the port. The WriteFile function is blocked until all requested characters are sent out. On the other hand, an overlapped operation will not finish until all the characters are transferred or the operation is aborted. The following conditions occur until the operation is completed:&lt;br /&gt;&lt;br /&gt;    * WaitForSingleObject always returns WAIT_TIMEOUT if a synchronization time-out is supplied. WaitForSingleObject will block forever if an INFINITE synchronization time-out is used.&lt;br /&gt;    * GetOverlappedResult always returns FALSE and GetLastError returns ERROR_IO_INCOMPLETE if called directly after the call to GetOverlappedResult.&lt;br /&gt;&lt;br /&gt;Setting the members of the COMMTIMEOUTS structure in the following manner causes read operations to complete immediately without waiting for any new data to arrive:&lt;br /&gt;&lt;br /&gt;COMMTIMEOUTS timeouts;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;timeouts.ReadIntervalTimeout = MAXDWORD; &lt;br /&gt;&lt;br /&gt;timeouts.ReadTotalTimeoutMultiplier = 0;&lt;br /&gt;&lt;br /&gt;timeouts.ReadTotalTimeoutConstant = 0;&lt;br /&gt;&lt;br /&gt;timeouts.WriteTotalTimeoutMultiplier = 0;&lt;br /&gt;&lt;br /&gt;timeouts.WriteTotalTimeoutConstant = 0;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;if (!SetCommTimeouts(hComm, &amp;timeouts))&lt;br /&gt;&lt;br /&gt;   // Error setting time-outs.&lt;br /&gt;&lt;br /&gt;These settings are necessary when used with an event-based read described in the “Caveat?section earlier. In order for ReadFile to return 0 bytes read, the ReadIntervalTimeout member of the COMMTIMEOUTS structure is set to MAXDWORD, and the ReadTimeoutMultiplier and ReadTimeoutConstant are both set to zero.&lt;br /&gt;&lt;br /&gt;An application must always specifically set communications time-outs when it uses a communications port. The behavior of read and write operations is affected by communications time-outs. When a port is initially open, it uses default time-outs supplied by the driver or time-outs left over from a previous communications application. If an application assumes that time-outs are set a certain way, while the time-outs are actually different, then read and write operations may never complete or may complete too often.&lt;br /&gt;Conclusion&lt;br /&gt;&lt;br /&gt;This article serves as a discussion of some of the common pitfalls and questions that arise when developing a serial communications application. The Multithreaded TTY sample that comes with this article is designed using many of the techniques discussed here. Download it and try it out. Learning how it works will provide a thorough understanding of the Win32 serial communications functions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-2312196180906972262?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/2312196180906972262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=2312196180906972262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/2312196180906972262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/2312196180906972262'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/07/serial-communications-in-win32.html' title='Serial Communications in Win32'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-8861722148852058380</id><published>2008-06-09T04:06:00.000-07:00</published><updated>2008-06-09T04:07:02.839-07:00</updated><title type='text'>Introduction to FIR Digital Filters</title><content type='html'>&lt;p class="deck"&gt;&lt;span style="font-size:130%;"&gt;Finite impulse response (FIR) filters are the most popular                  type of filters implemented in software. This introduction will                  help you understand them both on a theoretical and a practical                  level.&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Filters are signal conditioners. Each functions by accepting                  an input signal, blocking prespecified frequency components, and                  passing the original signal minus those components to the output.                  For example, a typical phone line acts as a filter that limits                  frequencies to a range considerably smaller than the range of                  frequencies human beings can hear. That's why listening to CD-quality                  music over the phone is not as pleasing to the ear as listening                  to it directly. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A digital filter takes a digital input, gives a digital                  output, and consists of digital components. In a typical digital                  filtering application, software running on a digital                  signal processor (DSP) reads input samples from an A/D                  converter, performs the mathematical manipulations dictated                  by theory for the required filter type, and outputs the result                  via a D/A converter. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;An analog filter, by contrast, operates directly on the                  analog inputs and is built entirely with analog components, such                  as resistors, capacitors, and inductors. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;There are many filter types, but the most common are lowpass,                  highpass, bandpass, and bandstop. A lowpass filter allows                  only low frequency signals (below some specified cutoff) through                  to its output, so it can be used to eliminate high frequencies.                  A lowpass filter is handy, in that regard, for limiting the uppermost                  range of frequencies in an audio signal; it's the type of filter                  that a phone line resembles. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A highpass filter does just the opposite, by rejecting                  only frequency components below some threshold. An example highpass                  application is cutting out the audible 60Hz AC power "hum", which                  can be picked up as noise accompanying almost any signal in the                  U.S. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The designer of a cell phone or any other sort of wireless transmitter                  would typically place an analog bandpass filter in its                  output RF stage, to ensure that only output signals within its                  narrow, government-authorized range of the frequency spectrum                  are transmitted. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Engineers can use bandstop filters, which pass both low and high                  frequencies, to block a predefined range of frequencies in the                  middle. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Frequency response&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Simple filters are usually defined by their responses to the                  individual frequency components that constitute the input signal.                  There are three different types of responses. A filter's response                  to different frequencies is characterized as passband, transition                  band, or stopband. The passband response is the filter's                  effect on frequency components that are passed through (mostly)                  unchanged. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;Frequencies within a filter's stopband are, by contrast,                  highly attenuated. The transition band represents frequencies                  in the middle, which may receive some attenuation but are not                  removed completely from the output signal. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;In Figure 1, which shows the frequency response of a lowpass                  filter, ω&lt;sub&gt;p&lt;/sub&gt; is the passband ending frequency,                  ω&lt;sub&gt;s&lt;/sub&gt; is the stopband beginning frequency,                  and A&lt;sub&gt;s&lt;/sub&gt; is the amount of attenuation in the stopband.                  Frequencies between ω&lt;sub&gt;p&lt;/sub&gt; and ω&lt;sub&gt;s&lt;/sub&gt;                 fall within the transition band and are attenuated to some lesser                  degree.&lt;/span&gt;&lt;/p&gt;                &lt;p align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;img src="http://www.netrino.com/images/articles/LowpassFilterResponse.gif" alt="low pass filter response" height="214" width="400" /&gt;&lt;/span&gt;&lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 1. The response of a lowpass filter                  to various input frequencies&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Given these individual filter parameters, one of numerous filter                  design software packages can generate the required signal processing                  equations and coefficients for implementation on a DSP. Before                  we can talk about specific implementations, however, some additional                  terms need to be introduced. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Ripple is usually specified as a peak-to-peak level in                  decibels. It describes how little or how much the filter's amplitude                  varies within a band. Smaller amounts of ripple represent more                  consistent response and are generally preferable. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Transition bandwidth describes how quickly a filter transitions                  from a passband to a stopband, or vice versa. The more rapid this                  transition, the higher the transition bandwidth; and the more                  difficult the filter is to achieve. Though an almost instantaneous                  transition to full attenuation is typically desired, real-world                  filters don't often have such ideal frequency response curves.                &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;There is, however, a tradeoff between ripple and transition bandwidth,                  so that decreasing either will only serve to increase the other.                &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Finite impulse response&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A finite impulse response (FIR) filter is a filter structure                  that can be used to implement almost any sort of frequency response                  digitally. An FIR filter is usually implemented by using a series                  of delays, multipliers, and adders to create the filter's output.                &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Figure 2 shows the basic block diagram for an FIR filter of length                  N. The delays result in operating on prior input samples.                  The h&lt;sub&gt;k&lt;/sub&gt; values are the coefficients used for                  multiplication, so that the output at time n is the summation                  of all the delayed samples multiplied by the appropriate coefficients.                &lt;/span&gt;&lt;/p&gt;                &lt;p align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;img src="http://www.netrino.com/images/articles/FIRFilterDesign.gif" alt="FIR filter block diagram" height="116" width="400" /&gt;&lt;/span&gt;&lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 2. The logical structure                  of an FIR filter&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The process of selecting the filter's length and coefficients                  is called filter design. The goal is to set those parameters such                  that certain desired stopband and passband parameters will result                  from running the filter. Most engineers utilize a program such                  as MATLAB to do their filter design. But whatever tool is used,                  the results of the design effort should be the same:&lt;/span&gt;&lt;/p&gt;               &lt;ul&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A frequency response plot, like the one shown in Figure 1,                    which verifies that the filter meets the desired specifications,                    including ripple and transition bandwidth.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;The filter's length and coefficients. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The longer the filter (more taps), the more finely the response                  can be tuned. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;With the length, N,                  and coefficients, &lt;span class="code"&gt;float                  h[N] = { ... }&lt;/span&gt;, decided upon, the implementation of the                  FIR filter is fairly straightforward. Listing 1 shows how it could                  be done in C. Running this code on a processor with a multiply-and-accumulate                 instruction (and a compiler that knows how to use it) is essential                  to achieving a large number of taps.&lt;/span&gt;&lt;/p&gt;  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;/*&lt;br /&gt;* Sample the input signal (perhaps via A/D).&lt;br /&gt;*/&lt;br /&gt;sample = input();&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Insert the newest sample into an N-sample circular buffer.&lt;br /&gt;* The oldest sample in the circular buffer is overwritten.&lt;br /&gt;*/&lt;br /&gt;x[oldest] = sample;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Multiply the last N inputs by the appropriate coefficients.&lt;br /&gt;* Their sum is the current output.&lt;br /&gt;*/&lt;br /&gt;y = 0;&lt;br /&gt;&lt;br /&gt;for (k = 0; k &lt; N; k++)&lt;br /&gt;{&lt;br /&gt;   y += h[k] * x[(oldest + k) % N];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;oldest = (oldest + 1) % N;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Output the result.&lt;br /&gt;*/&lt;br /&gt;output(y);&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;      &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 1. Implementation of an N-tap FIR filter                  in C&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;As you can see, an FIR filter simply produces a weighted average                  of its N most recent input samples. All of the magic is                  in the coefficients, which dictate the actual output for a given                  pattern of input samples. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Other digital filter structures are possible, including infinite                  impulse response (IIR), which uses feedback to keep more historical                  information active in the calculation. &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-8861722148852058380?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/8861722148852058380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=8861722148852058380' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8861722148852058380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8861722148852058380'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/06/introduction-to-fir-digital-filters.html' title='Introduction to FIR Digital Filters'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-6742742214774666571</id><published>2008-06-09T04:04:00.001-07:00</published><updated>2008-06-09T04:04:59.910-07:00</updated><title type='text'>Fast Accurate Memory Test Suite</title><content type='html'>&lt;p class="deck"&gt;&lt;span style="font-size:130%;"&gt;If ever there was a piece of embedded software ripe for                  reuse it's the memory test. This article shows how to test for                  the most common memory problems with a set of three efficient,                  portable, public-domain memory test functions.&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;One piece of software that nearly every embedded developer must                  write at some point in his career is a memory test. Often, once                  the prototype hardware is ready, the board's designer would like                  some reassurance that she has wired the address and data lines                  correctly, and that the various memory chips are working properly.                  Even if that's not the case, it is desirable to test any onboard                  RAM at least as often as the system is reset. It is up to the                  embedded software developer, then, to figure out what can go wrong                  and design a suite of tests that will uncover potential problems.                &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; At first glance, writing a memory test may seem like a fairly                  simple endeavor. However, as you look at the problem more closely                  you will realize that it can be difficult to detect subtle memory                  problems with a simple test. In fact, as a result of programmer                  naïveté, many embedded systems include memory tests                  that would detect only the most catastrophic memory failures.                  Perhaps unbelievably, some of these may not even notice that the                  memory chips have been removed from the board! &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; The purpose of a memory test is to confirm that each storage                  location in a memory device is working. In other words, if you                  store the value 50 at a particular address, you expect to find                  that value stored there until another value is written to that                  same address. The basic idea behind any memory test, then, is                  to write some set of data to each address in the memory device                  and verify the data by reading it back. If all the values read                  back are the same as those that were written, then the memory                  device is said to pass the test. As you will see, it is only through                  careful selection of the set of data values that you can be sure                  that a passing result is meaningful. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; Of course, a memory test like the one just described is necessarily                  destructive. In the process of testing the memory, you must overwrite                  its prior contents. Since it is usually impractical to overwrite                  the contents of nonvolatile memories, the tests described in this                  article are generally used only for RAM testing. However, if the                  contents of a non-volatile memory device, like flash, are unimportant--as                  they are during the product development stage--these same algorithms                  can be used to test those devices as well. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Common memory problems&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Before implementing any of the possible test algorithms, you                  should be familiar with the types of memory problems that are                  likely to occur. One common misconception among software engineers                  is that most memory problems occur within the chips themselves.                  Though a major issue at one time (a few decades ago), problems                  of this type are increasingly rare. These days, the manufacturers                  of memory devices perform a variety of post-production tests on                  each batch of chips. If there is a problem with a particular batch,                  it is extremely unlikely that one of the bad chips will make its                  way into your system. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; The one type of memory chip problem you could encounter is a                  catastrophic failure. This is usually caused by some sort of physical                  or electrical damage to the chip after manufacture. Catastrophic                  failures are uncommon and usually affect large portions of the                  chip. Since a large area is affected, it is reasonable to assume                  that catastrophic failure will be detected by any decent test                  algorithm. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; In my experience, the most common source of actual memory problems                  is the circuit board. Typical circuit board problems are problems                  with the wiring between the processor and memory device, missing                  memory chips, and improperly inserted memory chips. These are                  the problems that a good memory test algorithm should be able                  to detect. Such a test should also be able to detect catastrophic                  memory failures without specifically looking for them. So, let's                  discuss the circuit board problems in more detail. &lt;/span&gt;&lt;/p&gt;                &lt;h3&gt;&lt;span style="font-size:130%;"&gt;Electrical wiring problems&lt;/span&gt;&lt;/h3&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;An electrical wiring problem could be caused by an error in design                  or production of the board or as the result of damage received                  after manufacture. Each of the wires that connects the memory                  device to the processor is one of three types: an address line,                  a data line, or a control line. The address and data lines are                  used to select the memory location and to transfer the data, respectively.                  The control lines tell the memory device whether the processor                  wants to read or write the location and precisely when the data                  will be transferred. Unfortunately, one or more of these wires                  could be improperly routed or damaged in such a way that it is                  either shorted (for example, connected to another wire on the                  board) or open (not connected to anything). These problems are                  often caused by a bit of solder splash or a broken trace, respectively.                  Both cases are illustrated in Figure 1. &lt;/span&gt;&lt;/p&gt;               &lt;p align="center"&gt;                 &lt;span style="font-size:130%;"&gt;&lt;img src="http://www.netrino.com/images/articles/MemoryWiringProblems.gif" alt="shorts opens wiring problems" height="213" width="363" /&gt;&lt;/span&gt;                &lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 1. Possible wiring                  problems&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;Problems with the electrical connections to the processor will                  cause the memory device to behave incorrectly. Data may be stored                  incorrectly, stored at the wrong address, or not stored at all.                  Each of these symptoms can be explained by wiring problems on                  the data, address, and control lines, respectively. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; If the problem is with a data line, several data bits may appear                  to be "stuck together" (for example, two or more bits always contain                  the same value, regardless of the data transmitted). Similarly,                  a data bit may be either "stuck high" (always 1) or "stuck low"                  (always 0). These problems can be detected by writing a sequence                  of data values designed to test that each data pin can be set                  to 0 and 1, independently of all the others. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; If an address line has a wiring problem, the contents of two                  memory locations may appear to overlap. In other words, data written                  to one address will actually overwrite the contents of another                  address instead. This happens because an address bit that is shorted                  or open will cause the memory device to see an address different                  than the one selected by the processor. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; Another possibility is that one of the control lines is shorted                  or open. Although it is theoretically possible to develop specific                  tests for control line problems, it is not possible to describe                  a general test for them. The operation of many control signals                  is specific to either the processor or memory architecture. Fortunately,                  if there is a problem with a control line, the memory will probably                  not work at all, and this will be detected by other memory tests.                  If you suspect a problem with a control line, it is best to seek                  the advice of the board's designer before constructing a specific                  test. &lt;/span&gt;&lt;/p&gt;                &lt;h3&gt;&lt;span style="font-size:130%;"&gt;Missing memory chips&lt;/span&gt;&lt;/h3&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;A missing memory chip is clearly a problem that should be detected.                  Unfortunately, due to the capacitive nature of unconnected electrical                  wires, some memory tests will not detect this problem. For example,                  suppose you decided to use the following test algorithm: write                  the value 1 to the first location in memory, verify the value                  by reading it back, write 2 to the second location, verify the                  value, write 3 to the third location, verify, and so on. Since                  each read occurs immediately after the corresponding write, it                  is possible that the data read back represents nothing more than                  the voltage remaining on the data bus from the previous write.                  If the data is read back too quickly, it will appear that the                  data has been correctly stored in memory-even though there is                  no memory chip at the other end of the bus! &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; To detect a missing memory chip the test must be altered. Instead                  of performing the verification read immediately after the corresponding                  write, it is desirable to perform several consecutive writes followed                  by the same number of consecutive reads. For example, write the                  value 1 to the first location, 2 to the second location, and 3                  to the third location, then verify the data at the first location,                  the second location, and so on. If the data values are unique                  (as they are in the test just described), the missing chip will                  be detected: the first value read back will correspond to the                  last value written (3), rather than the first (1). &lt;/span&gt;&lt;/p&gt;                &lt;h3&gt;&lt;span style="font-size:130%;"&gt;Improperly inserted chips&lt;/span&gt;&lt;/h3&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;If a memory chip is present but improperly inserted in its socket,                  the system will usually behave as though there is a wiring problem                  or a missing chip. In other words, some number of the pins on                  the memory chip will either not be connected to the socket at                  all or will be connected at the wrong place. These pins will be                  part of the data bus, address bus, or control wiring. So as long                  as you test for wiring problems and missing chips, any improperly                  inserted chips will be detected automatically. &lt;/span&gt;&lt;/p&gt;               &lt;h3&gt;&lt;span style="font-size:130%;"&gt;Developing a test strategy&lt;/span&gt;&lt;/h3&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Before going on, let's quickly review the types of memory problems                  we must be able to detect. Memory chips only rarely have internal                  errors, but, if they do, they are probably catastrophic in nature                  and will be detected by any test. A more common source of problems                  is the circuit board, where a wiring problem may occur or a memory                  chip may be missing or improperly inserted. Other memory problems                  can occur, but the ones described here are the most common. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; By carefully selecting your test data and the order in which                  the addresses are tested, it is possible to detect all of the                  memory problems described above. It is usually best to break your                  memory test into small, single-minded pieces. This helps to improve                  the efficiency of the overall test and the readability of the                  code. More specific tests can also provide more detailed information                  about the source of the problem, if one is detected. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; I have found it is best to have three individual memory tests:                  a data bus test, an address bus test, and a device test. The first                  two tests detect electrical wiring problems and improperly inserted                  chips, while the third is intended to detect missing chips and                  catastrophic failures. As an unintended consequence, the device                  test will also uncover problems with the control bus wiring, though                  it will not provide useful information about the source of such                  a problem. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; The order in which you execute these three tests is important.                  The proper order is: data bus test first, followed by the address                  bus test, and then the device test. That's because the address                  bus test assumes a working data bus, and the device test results                  are meaningless unless both the address and data buses are known                  to be good. If any of the tests fail, you should work with the                  board's designer to locate the source of the problem. By looking                  at the data value or address at which the test failed, he or she                  should be able to quickly isolate the problem on the circuit board.                &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Data bus test&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The first thing we want to test is the data bus wiring. We need                  to confirm that any value placed on the data bus by the processor                  is correctly received by the memory device at the other end. The                  most obvious way to test that is to write all possible data values                  and verify that the memory device stores each one successfully.                  However, that is not the most efficient test available. A faster                  method is to test the bus one bit at a time. The data bus passes                  the test if each data bit can be set to 0 and 1, independently                  of the other data bits. &lt;/span&gt;&lt;/p&gt;                &lt;center&gt;                 &lt;table align="center" border="1" width="90"&gt;                   &lt;tbody&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000001 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000010 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                      &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000100 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00001000 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00010000 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                      &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00100000 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;01000000 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;10000000 &lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                    &lt;/tbody&gt;                 &lt;/table&gt;               &lt;/center&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Table 1. Consecutive data values                  for the walking 1's test&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;A good way to test each bit independently is to perform the so-called                  "walking 1's test." Table 1 shows the data patterns used in an                  8-bit version of this test. The name of this test comes from the                  fact that a single data bit is set to 1 and "walked" through the                  entire data word. The number of data values to test is the same                  as the width of the data bus. This reduces the number of test                  patterns from 2n to n, where n is the width of the data bus. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; Since we are testing only the data bus at this point, all of                  the data values can be written to the same address. Any address                  within the memory device will do. However, if the data bus splits                  as it makes its way to more than one memory chip, you will need                  to perform the data bus test at multiple addresses, one within                  each chip. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; To perform the walking 1's test, simply write the first data                  value in the table, verify it by reading it back, write the second                  value, verify, and so on. When you reach the end of the table,                  the test is complete. It is okay to do the read immediately after                  the corresponding write this time because we are not yet looking                  for missing chips. In fact, this test provides meaningful results                  even if the memory chips are not installed. &lt;/span&gt;&lt;/p&gt;  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;typedef unsigned char datum;    /* Set the data bus width to 8 bits.  */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/**********************************************************************&lt;br /&gt;*&lt;br /&gt;* Function:    memTestDataBus()&lt;br /&gt;*&lt;br /&gt;* Description: Test the data bus wiring in a memory region by&lt;br /&gt;*              performing a walking 1's test at a fixed address&lt;br /&gt;*              within that region.  The address (and hence the&lt;br /&gt;*              memory region) is selected by the caller.&lt;br /&gt;*&lt;br /&gt;* Notes:      &lt;br /&gt;*&lt;br /&gt;* Returns:     0 if the test succeeds. &lt;br /&gt;*              A non-zero result is the first pattern that failed.&lt;br /&gt;*&lt;br /&gt;**********************************************************************/&lt;br /&gt;datum&lt;br /&gt;memTestDataBus(volatile datum * address)&lt;br /&gt;{&lt;br /&gt;   datum pattern;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Perform a walking 1's test at the given address.&lt;br /&gt;    */&lt;br /&gt;   for (pattern = 1; pattern != 0; pattern &lt;&lt;= 1)&lt;br /&gt;   {&lt;br /&gt;       /*&lt;br /&gt;        * Write the test pattern.&lt;br /&gt;        */&lt;br /&gt;       *address = pattern;&lt;br /&gt;&lt;br /&gt;       /*&lt;br /&gt;        * Read it back (immediately is okay for this test).&lt;br /&gt;        */&lt;br /&gt;       if (*address != pattern)&lt;br /&gt;       {&lt;br /&gt;           return (pattern);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return (0);&lt;br /&gt;&lt;br /&gt;}   /* memTestDataBus() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;      &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 1. Data bus test&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The function memTestDataBus(),                  in Listing 1, shows how to implement the walking 1's test in C.                  It assumes that the caller will select the test address, and tests                  the entire set of data values at that address. If the data bus                  is working properly, the function will return 0. Otherwise it                  will return the data value for which the test failed. The bit                  that is set in the returned value corresponds to the first faulty                  data line, if any. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Address bus test &lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;After confirming that the data bus works properly, you should                  next test the address bus. Remember that address bus problems                  lead to overlapping memory locations. Many possible addresses                  could overlap. However, it is not necessary to check every possible                  combination. You should instead follow the example of the data                  bus test above and try to isolate each address bit during testing.                  You just need to confirm that each of the address pins can be                  set to 0 and 1 without affecting any of the others. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; The smallest set of addresses that will cover all possible combinations                  is the set of "power-of-two" addresses. These addresses are analogous                  to the set of data values used in the walking 1's test. The corresponding                  memory locations are 0001h,                  0002h, 0004h,                  0008h, 0010h,                  0020h, and so on.                  In addition, address 0000h                  must also be tested. The possibility of overlapping locations                  makes the address bus test harder to implement. After writing                  to one of the addresses, you must check that none of the others                  has been overwritten. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; It is important to note that not all of the address lines can                  be tested in this way. Part of the address-the leftmost bits-selects                  the memory chip itself. Another part-the rightmost bits-may not                  be significant if the data bus width is greater than eight bits.                  These extra bits will remain constant throughout the test and                  reduce the number of test addresses. For example, if the processor                  has 32 address bits, it can address up to 4GB of memory. If you                  want to test a 128K block of memory, the 15 most-significant address                  bits will remain constant. In that case, only the 17 rightmost                  bits of the address bus can actually be tested. (128K is 1/32,768th                  of the total 4GB address space.)&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; To confirm that no two memory locations overlap, you should                  first write some initial data value at each power-of-two offset                  within the device. Then write a new value-an inverted copy of                  the initial value is a good choice-to the first test offset, and                  verify that the initial data value is still stored at every other                  power-of-two offset. If you find a location, other than the one                  just written, that contains the new data value, you have found                  a problem with the current address bit. If no overlapping is found,                  repeat the procedure for each of the remaining offsets. &lt;/span&gt;&lt;/p&gt;  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;/**********************************************************************&lt;br /&gt;*&lt;br /&gt;* Function:    memTestAddressBus()&lt;br /&gt;*&lt;br /&gt;* Description: Test the address bus wiring in a memory region by&lt;br /&gt;*              performing a walking 1's test on the relevant bits&lt;br /&gt;*              of the address and checking for aliasing. This test&lt;br /&gt;*              will find single-bit address failures such as stuck&lt;br /&gt;*              -high, stuck-low, and shorted pins.  The base address&lt;br /&gt;*              and size of the region are selected by the caller.&lt;br /&gt;*&lt;br /&gt;* Notes:       For best results, the selected base address should&lt;br /&gt;*              have enough LSB 0's to guarantee single address bit&lt;br /&gt;*              changes.  For example, to test a 64-Kbyte region,&lt;br /&gt;*              select a base address on a 64-Kbyte boundary.  Also,&lt;br /&gt;*              select the region size as a power-of-two--if at all&lt;br /&gt;*              possible.&lt;br /&gt;*&lt;br /&gt;* Returns:     NULL if the test succeeds. &lt;br /&gt;*              A non-zero result is the first address at which an&lt;br /&gt;*              aliasing problem was uncovered.  By examining the&lt;br /&gt;*              contents of memory, it may be possible to gather&lt;br /&gt;*              additional information about the problem.&lt;br /&gt;*&lt;br /&gt;**********************************************************************/&lt;br /&gt;datum *&lt;br /&gt;memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes)&lt;br /&gt;{&lt;br /&gt;   unsigned long addressMask = (nBytes/sizeof(datum) - 1);&lt;br /&gt;   unsigned long offset;&lt;br /&gt;   unsigned long testOffset;&lt;br /&gt;&lt;br /&gt;   datum pattern     = (datum) 0xAAAAAAAA;&lt;br /&gt;   datum antipattern = (datum) 0x55555555;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Write the default pattern at each of the power-of-two offsets.&lt;br /&gt;    */&lt;br /&gt;   for (offset = 1; (offset &amp;amp; addressMask) != 0; offset &lt;&lt;= 1)&lt;br /&gt;   {&lt;br /&gt;       baseAddress[offset] = pattern;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Check for address bits stuck high.&lt;br /&gt;    */&lt;br /&gt;   testOffset = 0;&lt;br /&gt;   baseAddress[testOffset] = antipattern;&lt;br /&gt;&lt;br /&gt;   for (offset = 1; (offset &amp;amp; addressMask) != 0; offset &lt;&lt;= 1)&lt;br /&gt;   {&lt;br /&gt;       if (baseAddress[offset] != pattern)&lt;br /&gt;       {&lt;br /&gt;           return ((datum *) &amp;amp;baseAddress[offset]);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   baseAddress[testOffset] = pattern;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Check for address bits stuck low or shorted.&lt;br /&gt;    */&lt;br /&gt;   for (testOffset = 1; (testOffset &amp;amp; addressMask) != 0; testOffset &lt;&lt;= 1)&lt;br /&gt;   {&lt;br /&gt;       baseAddress[testOffset] = antipattern;&lt;br /&gt;&lt;br /&gt;  if (baseAddress[0] != pattern)&lt;br /&gt;  {&lt;br /&gt;   return ((datum *) &amp;amp;baseAddress[testOffset]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;       for (offset = 1; (offset &amp;amp; addressMask) != 0; offset &lt;&lt;= 1)&lt;br /&gt;       {&lt;br /&gt;           if ((baseAddress[offset] != pattern) &amp;amp;&amp;amp; (offset != testOffset))&lt;br /&gt;           {&lt;br /&gt;               return ((datum *) &amp;amp;baseAddress[testOffset]);&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       baseAddress[testOffset] = pattern;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return (NULL);&lt;br /&gt;&lt;br /&gt;}   /* memTestAddressBus() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;   &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 2. Address bus test&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The function memTestAddressBus(),                  in Listing 2, shows how this can be done in practice. The function                  accepts two parameters. The first parameter is the base address                  of the memory block to be tested and the second is its size, in                  bytes. The size is used to determine which address bits should                  be tested. For best results, the base address should contain a                  0 in each of those bits. If the address bus test fails, the address                  at which the first error was detected will be returned. Otherwise,                  this function returns NULL to indicate success. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Device test&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Once you know that the address and data bus wiring are working,                  it is necessary to test the integrity of the memory device itself.                  The thing to test is that every bit in the device is capable of                  holding both 0 and 1. This is a fairly straightforward test to                  implement, but takes significantly longer to execute than the                  previous two. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; For a complete device test, you must visit (write and verify)                  every memory location twice. You are free to choose any data value                  for the first pass, so long as you invert that value during the                  second. And since there is a possibility of missing memory chips,                  it is best to select a set of data that changes with (but is not                  equivalent to) the address. A simple example is an "increment                  test." &lt;/span&gt;&lt;/p&gt;                &lt;center&gt;                 &lt;table align="center" border="1" width="250"&gt;                   &lt;tbody&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Offset&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Value&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Inverted Value&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                      &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00h&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000001&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111110&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;01h&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000010&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111101&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;02h&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000011&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111100&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                      &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;03h&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000100&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111011&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                     &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;FEh&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111111&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000000&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                      &lt;tr&gt;                        &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;FFh&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;00000000&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                       &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11111111&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;                     &lt;/tr&gt;                   &lt;/tbody&gt;                 &lt;/table&gt;               &lt;/center&gt;                &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Table 2. Data values for an increment test&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; The offsets and corresponding data values for the increment                  test are shown in the first two columns of Table 2. The third                  column shows the inverted data values used during the second pass                  of this test. The latter represents a decrement test. There are                  many other possible choices of data, but the incrementing data                  pattern is adequate and easy to compute. &lt;/span&gt;&lt;/p&gt; &lt;pre&gt;&lt;span style="font-size:130%;"&gt;/**********************************************************************&lt;br /&gt;*&lt;br /&gt;* Function:    memTestDevice()&lt;br /&gt;*&lt;br /&gt;* Description: Test the integrity of a physical memory device by&lt;br /&gt;*              performing an increment/decrement test over the&lt;br /&gt;*              entire region.  In the process every storage bit&lt;br /&gt;*              in the device is tested as a zero and a one.  The&lt;br /&gt;*              base address and the size of the region are&lt;br /&gt;*              selected by the caller.&lt;br /&gt;*&lt;br /&gt;* Notes:      &lt;br /&gt;*&lt;br /&gt;* Returns:     NULL if the test succeeds.&lt;br /&gt;*&lt;br /&gt;*              A non-zero result is the first address at which an&lt;br /&gt;*              incorrect value was read back.  By examining the&lt;br /&gt;*              contents of memory, it may be possible to gather&lt;br /&gt;*              additional information about the problem.&lt;br /&gt;*&lt;br /&gt;**********************************************************************/&lt;br /&gt;datum *&lt;br /&gt;memTestDevice(volatile datum * baseAddress, unsigned long nBytes) &lt;br /&gt;{&lt;br /&gt;   unsigned long offset;&lt;br /&gt;   unsigned long nWords = nBytes / sizeof(datum);&lt;br /&gt;&lt;br /&gt;   datum pattern;&lt;br /&gt;   datum antipattern;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Fill memory with a known pattern.&lt;br /&gt;    */&lt;br /&gt;   for (pattern = 1, offset = 0; offset &lt; nWords; pattern++, offset++)&lt;br /&gt;   {&lt;br /&gt;       baseAddress[offset] = pattern;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Check each location and invert it for the second pass.&lt;br /&gt;    */&lt;br /&gt;   for (pattern = 1, offset = 0; offset &lt; nWords; pattern++, offset++)&lt;br /&gt;   {&lt;br /&gt;       if (baseAddress[offset] != pattern)&lt;br /&gt;       {&lt;br /&gt;           return ((datum *) &amp;amp;baseAddress[offset]);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       antipattern = ~pattern;&lt;br /&gt;       baseAddress[offset] = antipattern;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Check each location for the inverted pattern and zero it.&lt;br /&gt;    */&lt;br /&gt;   for (pattern = 1, offset = 0; offset &lt; nWords; pattern++, offset++)&lt;br /&gt;   {&lt;br /&gt;       antipattern = ~pattern;&lt;br /&gt;       if (baseAddress[offset] != antipattern)&lt;br /&gt;       {&lt;br /&gt;           return ((datum *) &amp;amp;baseAddress[offset]);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return (NULL);&lt;br /&gt;&lt;br /&gt;}   /* memTestDevice() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;       &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 3. Device test&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The function memTestDevice(),                  in Listing 3, implements just such a two-pass increment/decrement                  test. It accepts two parameters from the caller. The first parameter                  is the starting address and the second is the number of bytes                  to be tested. These parameters give the user maximum control over                  which areas of memory will be overwritten. The function will return                  NULL on success. Otherwise, the first address containing an incorrect                  data value is returned. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Putting it all together&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;To make our discussion more concrete, let's consider a practical                  example. Suppose that we wanted to test a 64K chunk of SRAM at                  address 00000000h.                  To do this, we call each of the three test routines in the proper                  order, as shown in Listing 4. In each case, the first parameter                  is the base address of the memory block. If the width of the data                  bus is greater than eight bits, a couple of modifications are                  required. &lt;/span&gt;&lt;/p&gt;  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;int&lt;br /&gt;memTest(void)&lt;br /&gt;{&lt;br /&gt;#define BASE_ADDRESS  (volatile datum *) 0x00000000&lt;br /&gt;#define NUM_BYTES     (64 * 1024)&lt;br /&gt;&lt;br /&gt;   if ((memTestDataBus(BASE_ADDRESS) != 0) ||&lt;br /&gt;       (memTestAddressBus(BASE_ADDRESS, NUM_BYTES) != NULL) ||&lt;br /&gt;       (memTestDevice(BASE_ADDRESS, NUM_BYTES) != NULL))&lt;br /&gt;   {&lt;br /&gt;       return (-1);&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;       return (0);&lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;}   /* memTest() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;      &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 4. Memory test engine&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; If any of the individual memory test routines returns a nonzero                  (or non-NULL) value, you might turn on a red LED to visually indicate                  the error. Otherwise, after all three tests have completed successfully,                  you might turn on a green LED. In the event of an error, the test                  routine that failed will return some information about the problem                  encountered. This information can be useful when communicating                  with the hardware designer or technician about the nature of the                  problem. However, it is visible only if we are running the test                  program in a debugger or emulator. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; In most cases, you would simply download the entire suite and                  let it run. Then, if and only if a memory problem is found, would                  you need to use a debugger to step through the program and examine                  the individual function return codes and contents of the memory                  device to see which test failed and why. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt; Unfortunately, it is not always possible to write memory tests                  in a high-level language. For example, the C language requires                  the use of a stack. But a stack itself requires working memory.                  This might be reasonable in a system with more than one memory                  device. For example, you might create a stack in an area of RAM                  that is already known to be working, while testing another memory                  device. In a situation such as this, a small SRAM could be tested                  from assembly and the stack could be created there afterward.                  Then a larger block of DRAM could be tested using a better test                  suite, like the one shown here. If you cannot assume enough working                  RAM for the stack and data needs of the test program, then you                  will need to rewrite these memory test routines entirely in assembly                  language. Another option is to run the memory test program from                  an in-circuit emulator. In this case, you could choose to place                  the stack in an area of the emulator's own internal memory. By                  moving the emulator's internal memory around in the target memory                  map, you could systematically test each memory device on the target.                &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt; The need for memory testing is most apparent during product                  development, when the reliability of the hardware and its design                  are still unproven. However, memory is one of the most critical                  resources in any embedded system, so it may also be desirable                  to include a memory test in the final release of your software.                  In that case, the memory test, and other hardware confidence tests,                  should be run each time the system is powered-on or reset. Together,                  this initial test suite forms a set of hardware diagnostics. If                  one or more of the diagnostics fail, a repair technician can be                  called in to diagnose the problem and repair or replace the faulty                  hardware. &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-6742742214774666571?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/6742742214774666571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=6742742214774666571' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/6742742214774666571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/6742742214774666571'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/06/fast-accurate-memory-test-suite.html' title='Fast Accurate Memory Test Suite'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-8361357705276846633</id><published>2008-06-09T04:03:00.001-07:00</published><updated>2008-06-09T04:03:51.032-07:00</updated><title type='text'>CRC Mathematics and Theory</title><content type='html'>&lt;p class="deck"&gt;&lt;span style="font-size:130%;"&gt;Checksum algorithms based solely on addition are easy                  to implement and can be executed efficiently on any microcontroller. However, many common                  types of transmission errors cannot be detected when such simple                  checksums are used. This article describes a stronger type                  of checksum, commonly known as a CRC.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:130%;"&gt;A cyclic redundancy check (CRC) is                  is based on division instead of addition. The error detection capabilities                  of a CRC make it a much stronger checksum and, therefore, often                  worth the price of additional computational complexity.&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;Additive checksums are error detection codes as opposed to error correction codes. A mismatch in the checksum will tell you there's been an error but not where or how to fix it. In implementation terms, there's not much difference between an error detection code and an error correction code. In both cases, you take the message you want to send, compute some mathematical function over its bits (usually called a checksum), and append the resulting bits to the message during transmission. &lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Error correction&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The difference between error detection and error correction lies                  primarily in what happens next. If the receiving system detects                  an error in the packet--for example, the received checksum bits                  do not accurately describe the received message bits--it may either                  discard the packet and request a retransmission (error detection)                  or attempt to repair the damage on its own (error correction). If packet                  repairs are to be attempted, the checksum is said to be an error                  correcting code. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The key to repairing corrupted packets is a stronger checksum algorithm.                  Specifically, what's needed is a checksum algorithm that distributes                  the set of valid bit sequences randomly and evenly across the                  entire set of possible bit sequences. For example, if the minimum number                  of bits that must change to turn any one valid packet into some                  other valid packet is seven, then any packet with three or fewer                  bit inversions can be corrected automatically by the receiver.                  (If four bit errors occur during transmission, the packet will                  seem closer to some other valid packet with only three errors                  in it.) In this case, error correction can only be done for up                  to three bit errors, while error detection can be done for up                  to six. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;This spreading of the valid packets across the space of possible                  packets can be measured by the Hamming distance, which                  is the number of bit positions in which any two equal-length packets                  differ. In other words, it's the number of bit errors that must                  occur if one of those packets is to be incorrectly received as                  the other. A simple example is the case of the two binary strings                  1001001 and 1011010,                  which are separated by a Hamming distance of three. (To see which                  bits must be changed, simply XOR the two strings together and                  note the bit positions that are set. In our example, the result                  is 0010011.) &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The beauty of all this is that the mere presence of an error                  detection or correction code within a packet means that not all                  of the possible packets are valid. Figure 1 shows what a packet                  looks like after a checksum has been appended to it. Since the                  checksum bits contain redundant information (they are completely                  a function of the message bits that precede them), not all of                  the 2&lt;sup&gt;(m+c)&lt;/sup&gt; possible packets are valid packets. In fact,                  the stronger the checksum algorithm used, the greater the number                  of invalid packets will be. &lt;/span&gt;&lt;/p&gt;                &lt;p align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;img alt="Packet Containing Message and Checksum" src="http://www.netrino.com/images/articles/CRC_Packet.gif" height="66" width="314" /&gt;&lt;/span&gt;&lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 1. A packet of information including checksum&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;By adjusting the ratio of the lengths m and c and carefully                  selecting the checksum algorithm, we can increase the number of                  bits that must be in error for any one valid packet to be inadvertently                  changed into another valid packet during transmission or storage                  and, hence, the likelihood of successful transmission. In essence,                  what we want to do is to maximize the "minimum Hamming distance                  across the entire set of valid packets." In other words, to distribute                  the set of 2&lt;sup&gt;m&lt;/sup&gt; valid packets as evenly as possible across                  the set of possible bit sequences of length m + c. This                  has the useful real-world effect of increasing the percentage                  of detectable and/or correctable errors. &lt;/span&gt;&lt;/p&gt;                 &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Binary long division &lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;It turns out that once you start to focus on maximizing the "minimum                  Hamming distance across the entire set of valid packets," it becomes                  obvious that simple checksum algorithms based on binary addition                  don't have the necessary properties. A change in one of the message                  bits does not affect enough of the checksum bits during addition.                  Fortunately, you don't have to develop a better checksum algorithm                  on your own. Researchers figured out long ago that modulo-2 binary                  division is the simplest mathematical operation that provides                  the necessary properties for a strong checksum. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;All of the CRC formulas you will encounter are simply checksum                  algorithms based on modulo-2 binary division. Though some differences                  exist in the specifics across different CRC formulas, the basic                  mathematical process is always the same: &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;                &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;The message bits are appended with c zero bits; this                    augmented message is the dividend&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A predetermined c+1-bit binary sequence, called the                    "generator polynomial", is the divisor&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;The checksum is the c-bit remainder that results from                    the division operation&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;In other words, you divide the augmented message by the generator                  polynomial, discard the quotient, and use the remainder as your                  checksum. It turns out that the mathematically appealing aspect                  of division is that remainders fluctuate rapidly as small numbers                  of bits within the message are changed. Sums, products, and quotients                  do not share this property. To see what I mean, look at the example                  of modulo-2 division in Figure 2. In this example, the message                  contains eight bits while the checksum is to have four bits. As                  the division is performed, the remainder takes the values 0111,                  1111, 0101,                  1011, 1101,                  0001, 0010,                  and, finally, 0100.                  The final remainder becomes the checksum for the given message.                &lt;/span&gt;&lt;/p&gt;                &lt;p align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;img alt="Modulo-2 Binary Division Example" src="http://www.netrino.com/images/articles/CRC_Modulo2Division.gif" height="278" width="325" /&gt;&lt;/span&gt;&lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 2. An example of modulo-2 binary division&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;For most people, the overwhelmingly confusing thing about CRCs                  is the implementation. Knowing that all CRC algorithms are simply                  long division algorithms in disguise doesn't help. Modulo-2 binary                  division doesn't map well to the instruction sets of general-purpose                  processors. So, whereas the implementation of a checksum algorithm                  based on addition is straightforward, the implementation of a                  binary division algorithm with an m+c-bit numerator and                  a c+1-bit denominator is nowhere close. [1]                  For one thing, there aren't generally any m+c or c+1-bit                  registers in which to store the operands. You will learn how to deal                  with this problem in the next article, where I talk about                  various software implementations of the CRC algorithms. For now,                  let's just focus on their strengths and weaknesses as potential                  checksums. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Generator polynomials&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Why is the predetermined c+1-bit divisor that's used to                  calculate a CRC called a generator polynomial? In my opinion,                  far too many explanations of CRCs actually try to answer that                  question. This leads their authors and readers down a long path                  that involves tons of detail about polynomial arithmetic and the                  mathematical basis for the usefulness of CRCs. This academic stuff                  is not important for understanding CRCs sufficiently to implement                  and/or use them and serves only to create potential confusion.                  So I'm not going to answer that question here. [2]&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Suffice it to say here only that the divisor is sometimes called                  a generator polynomial and that you should never make up the divisor's                  value on your own. Several mathematically well-understood generator                  polynomials have been adopted as parts of various international                  communications standards; you should always use one of those.                  If you have a background in polynomial arithmetic then you know                  that certain generator polynomials are better than others for                  producing strong checksums. The ones that have been adopted internationally                  are among the best of these. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Table 1 lists some of the most commonly used generator polynomials                  for 16- and 32-bit CRCs. Remember that the width of the divisor                  is always one bit wider than the remainder. So, for example, you'd                  use a 17-bit generator polynomial whenever a 16-bit checksum is                  required. &lt;/span&gt;&lt;/p&gt; &lt;center&gt;               &lt;table align="center" border="2" cellpadding="4" width="0%"&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;Checksum Width&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;Generator Polynomial&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;CRC-CCITT&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;16 bits&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;10001000000100001&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;CRC-16&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;16 bits&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;11000000000000101&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;CRC-32&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;32 bits&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div align="center"&gt;&lt;span style="font-size:130%;"&gt;100000100110000010001110110110111&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;               &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Table 1. International standard CRC polynomials&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;As is the case with other types of checksums, the width of the                  CRC plays an important role in the error detection capabilities                  of the algorithm. Ignoring special types of errors that are always                  detected by a particular checksum algorithm, the percentage of                  detectable errors is limited strictly by the width of a checksum.                  A checksum of c bits can only take one of 2&lt;sup&gt;c&lt;/sup&gt; unique                  values. Since the number of possible messages is significantly                  larger than that, the potential exists for two or more messages                  to have an identical checksum. If one of those messages is somehow                  transformed into one of the others during transmission, the checksum                  will appear correct and the receiver will unknowingly accept a                  bad message. The chance of this happening is directly related                  to the width of the checksum. Specifically, the chance of such                  an error is 1/2&lt;sup&gt;c&lt;/sup&gt;. Therefore, the probability of any random                  error being detected is 1-1/2&lt;sup&gt;c&lt;/sup&gt;. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;To repeat, the probability of detecting any random error increases                  as the width of the checksum increases. Specifically, a 16-bit                  checksum will detect 99.9985% of all errors. This is far better                  than the 99.6094% detection rate of an eight-bit checksum, but                  not nearly as good as the 99.9999% detection rate of a 32-bit                  checksum. All of this applies to both CRCs and addition-based                  checksums. What really sets CRCs apart, however, is the number                  of special cases that can be detected 100% of the time. For example,                  I pointed out last month that two opposite bit inversions (one                  bit becoming 0, the other becoming 1) in the same column of an                  addition would cause the error to be undetected. Well, that's                  not the case with a CRC. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;By using one of the mathematically well-understood generator                  polynomials like those in Table 1 to calculate a checksum, it's                  possible to state that the following types of errors will be detected                  without fail:&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;                &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A message with any one bit in error&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A message with any two bits in error (no matter how far apart,                    which column, and so on)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A message with any odd number of bits in error (no matter                    where they are)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:130%;"&gt;A message with an error burst as wide as the checksum itself                  &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;                              &lt;p&gt;&lt;span style="font-size:130%;"&gt;The first class of detectable error is also detected by an addition-based                  checksum, or even a simple parity bit. However, the middle two                  classes of errors represent much stronger detection capabilities                  than those other types of checksum. The fourth class of detectable                  error sounds at first to be similar to a class of errors detected                  by addition-based checksums, but in the case of CRCs, any odd                  number of bit errors will be detected. So the set of error bursts                  too wide to detect is now limited to those with an even number                  of bit errors. All other types of errors fall into the relatively                  high 1-1/2&lt;sup&gt;c&lt;/sup&gt; probability of detection. &lt;/span&gt;&lt;/p&gt;               &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Ethernet, SLIP, and PPP &lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Ethernet, like most physical layer protocols,                  employs a CRC rather than an additive checksum. Specifically,                  it employs the CRC-32 algorithm. The likelihood of an error in                  a packet sent over Ethernet being undetected is, therefore, extremely                  low. Many types of common transmission errors are detected 100%                  of the time, with the less likely ones detected 99.9999% of the                  time. Even if an error would somehow manage to get through at                  the Ethernet layer, it would probably be detected at the IP layer                  checksum (if the error is in the IP header) or in the TCP or UDP                  layer checksum above that. After all the chances of two or more                  different checksum algorithms not detecting the same error is                  extremely remote. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;However, many embedded systems that use TCP/IP will not employ                  Ethernet. Instead, they will use either the serial line Internet                  protocol (SLIP) or point-to-point protocol (PPP) to send and receive                  IP packets directly over a serial connection of some sort. Unfortunately,                  SLIP does not add a checksum or a CRC to the data from the layers                  above. So unless a pair of modems with error correction capabilities                  sits in between the two communicating systems, any transmission                  errors must hope to be detected by the relatively weak, addition-based                  Internet checksum described last month. The newer, compressed                  SLIP (CSLIP) shares this weakness with its predecessor. PPP, on                  the other hand, does include a 16-bit CRC in each of its frames,                  which can carry the same maximum size IP packet as an Ethernet                  frame. So while PPP doesn't offer the same amount of error detection                  capability as Ethernet, by using PPP you'll at least avoid the                  much larger number of undetected errors that may occur with SLIP                  or CSLIP. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Read my article on CRC calculations in C,                  to learn about various software implementations of CRCs. We'll start                  with an inefficient, but comprehendible, implementation and work                  to gradually increase its efficiency. You'll see then that the                  desire for an efficient implementation is the cause of much of                  the confusion surrounding CRCs. In the meantime, stay connected..                &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-8361357705276846633?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/8361357705276846633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=8361357705276846633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8361357705276846633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8361357705276846633'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/06/crc-mathematics-and-theory.html' title='CRC Mathematics and Theory'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-5317012962813000083</id><published>2008-06-09T04:00:00.000-07:00</published><updated>2008-06-09T04:02:31.337-07:00</updated><title type='text'>Additive Checksums</title><content type='html'>&lt;p class="deck"&gt;&lt;span style="font-size:130%;"&gt;Whenever you connect two or more computers together with                  the intent of exchanging information, you assume that the exchange                  will take place without errors. But what if some of the data is                  lost or corrupted in transit? Communication protocols usually                  attempt to detect such errors automatically. To do that they use                  checksums.&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The most important part of listening to someone speak is ensuring                  that you've heard them correctly. Your brain performs the tasks                  of error detection and correction for you, automatically. It does                  this by examining extra bits of information from the speaker and                  the speech; if a phrase or sentence makes sense as a whole and                  it makes sense coming from the mouth of the particular speaker,                  then the individual words were probably heard correctly. The same                  principle applies when you are reading. But what happens when                  computers are communicating with one another? How does the receiving                  computer know if an error has occurred in transmission? &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Establishing correctness is more difficult for computers than                  humans. At the lowest level, communication between computers consists                  of nothing but a stream of binary digits. Meaning is only assigned                  to that particular sequence of bits at higher levels. We call                  that meaningful sequence of bits the message; it is analogous                  to a spoken or written phrase. If one or more bits within the                  message are inverted (a logic one becomes a logic zero, or vice                  versa) as it travels between computers, the receiver has no way                  to detect the error. No environmental or syntactical context is                  available to the receiver, since it cannot understand the message                  in its transmitted form. &lt;/span&gt;&lt;/p&gt;              &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Achieving parity&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;If we want communicating computers to detect and correct transmission                  errors automatically, we must provide a replacement for context.                  This usually takes the form of an error correction code or error                  detection code. A simple type of error detection code that you                  are probably already familiar with is called a parity bit. A parity                  bit is a single, extra binary digit that is appended to the message                  by the sender and transmitted along with it. Depending on the                  type of parity used, the parity bit ensures that the total number                  of logic ones sent is even (even parity) or odd (odd parity).                  For an example of even parity, consider the sequence:&lt;/span&gt;&lt;/p&gt;                  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;10101110 1&lt;/span&gt;&lt;/pre&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;in which the eight-bit message contains five ones and three zeros.                  The parity bit is one in this case to force the total number of                  ones in the transmitted data stream to be even. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;When a parity bit is appended to a message, one additional bit                  of data must be sent between the computers. So there must be some                  benefit associated with the lost bandwidth. The most obvious benefit                  is that if any single bit in the message is inverted during transmission,                  the number of ones will either increase or decrease by one, thus                  making the received number of ones odd and the parity incorrect.                  The receiver can now detect such an error automatically and request                  a retransmission of the entire stream of bits. Interestingly,                  the receiver can also now detect any odd number of bit inversions.                  (Note that all of this still applies even when the parity bit                  is one of the inverted bits.) &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;However, as you may have already noticed, if two bits are inverted                  (two ones become zeros, for example), the parity of the stream                  of bits will not change; a receiver will not be able to detect                  such errors. In fact, the same is true for any even number of                  bit inversions. A parity bit is a weak form of error detection                  code. It has a small cost (one bit per message), but it is unable                  to detect many types of possible errors. (By the way, odd parity                  has the same costs, benefits, and weaknesses as even parity.)                &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Perhaps this is not acceptable for your application. An alternative                  that might occur to you is to send the entire message twice. If                  you're already spending bandwidth sending an error detection code,                  why not spend half of the bandwidth? The problem is that you could                  actually be spending much more than half of the available bandwidth.                  If a computer receives two copies of a message and the bits that                  comprise them aren't exactly the same, it cannot tell which one                  of the two is correct. In fact, it may be that both copies contain                  errors. So the receiver must request a retransmission whenever                  there is a discrepancy between the message and the copy sent as                  an error detection code. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;With that in mind, let's compare the bandwidth costs of using                  a parity bit vs. resending the entire message. We'll assume that                  all messages are 1,000-bits long and that the communications channel                  has a bit error rate (average number of inverted bits) of one                  per 10,000 bits sent. Using a parity bit, we'd spend 0.1% of our                  bandwidth sending the error detection code (one bit of error protection                  for 1,000 bits of message) and have to retransmit one out of every                  10 messages due to errors. If we send two complete copies of each                  message instead, the smallest unit of transmission is 2,000 bits                  (50% of our bandwidth is now spent sending the error detection                  code). In addition, we'll have to retransmit one out of every                  five messages. Therefore, the achievable bandwidths are approximately                  90% and 40%, respectively. As the width of the code increases,                  the message plus code lengthens and becomes more vulnerable to                  bit errors and, as a result, expensive retransmissions. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;From this type of analysis it should be clear that keeping the                  size of an error detection code as small as possible is a good                  thing, even if it does mean that some types of errors will be                  undetectable. (Note that even sending two copies of the message                  is not a perfect solution. If the same bit errors should happen                  to occur in both copies, the errors will not be detected by the                  receiver.) In addition to reducing the bandwidth cost of transmitting                  the error detection code itself, this also increases the message                  throughput. But we still don't want to go so far as using a one-bit                  error detection scheme like parity. That would let too many possible                  errors escape detection. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;In practice, of course, we can achieve far better error detection                  capabilities than just odd numbers of inverted bits. But in order                  to do so we have to use error detection codes that are more complex                  than simple parity, and also contain more bits. I'll spend the                  remainder of this column and most of the next two discussing the                  strengths and weaknesses of various types of checksums, showing                  you how to compute them, and explaining how each can be best employed                  for purposes of error detection. &lt;/span&gt;&lt;/p&gt;                &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Checksums&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;As the name implies, a checksum usually involves a summation                  of one sort or another. For example, one of the most common checksum                  algorithms involves treating the message like a sequence of bytes                  and summing them. Listing 1 shows how this simple algorithm might                  be implemented in C.&lt;/span&gt;&lt;/p&gt; &lt;pre&gt;&lt;span style="font-size:130%;"&gt;uint8_t&lt;br /&gt;Sum(uint8_t const message[], int nBytes)&lt;br /&gt;{&lt;br /&gt;   uint8_t  sum = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   while (nBytes-- &gt; 0)&lt;br /&gt;   {&lt;br /&gt;       sum += *(message++);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return (sum);&lt;br /&gt;&lt;br /&gt;}   /* Sum() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;  &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 1. A sum-of-bytes checksum&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The sum-of-bytes algorithm is straightforward to compute. However,                  understanding its strengths and weaknesses as a checksum is more                  difficult. What types of errors does it detect? What errors is                  it unable to detect? These are important factors to consider whenever                  you are selecting a checksum algorithm for a particular application.                  You want the algorithm you choose to be well matched to the types                  of errors you expect to occur in your transmission environment.                  For example, a parity bit would be a poor choice for a checksum                  if bit errors will frequently occur in pairs. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A noteworthy weakness of the sum-of-bytes algorithm is that no                  error will be detected if the entire message and data are somehow                  received as a string of all zeros. (A message of all zeros is                  a possibility, and the sum of a large block of zeros is still                  zero.) The simplest way to overcome this weakness is to add a                  final step to the checksum algorithm: invert the bits of the final                  sum. The new proper checksum for a message of all zeros would                  be FFh. That way, if the message and checksum are both all zeros,                  the receiver will know that something's gone terribly wrong. A                  modified version of the checksum implementation is shown in Listing                  2. &lt;/span&gt;&lt;/p&gt; &lt;pre&gt;&lt;span style="font-size:130%;"&gt;uint8_t&lt;br /&gt;SumAndInvert(uint8_t const message[], int nBytes)&lt;br /&gt;{&lt;br /&gt;   uint8_t  sum = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   while (nBytes-- &gt; 0)&lt;br /&gt;   {&lt;br /&gt;       sum += *(message++);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return (~sum);&lt;br /&gt;&lt;br /&gt;}   /* SumAndInvert() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 2. A slightly more robust sum-of-bytes checksum algorithm&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;This final inversion does not affect any of the other error detection                  capabilities of this checksum, so let's go back to discussing                  the basic sum-of-bytes algorithm in Listing 1. First, it should                  be obvious that any single bit inversion in the message or checksum                  will be detectable. Such an error will always affect at least                  one bit within the checksum. (It could affect more, of course,                  but not less.) Observe that the sum-of-bytes is performed by essentially                  lining up all of the bytes that comprise the message and performing                  addition on them, like this:&lt;/span&gt;&lt;/p&gt; &lt;pre&gt;&lt;span style="font-size:130%;"&gt;  10110101&lt;br /&gt; 11000000&lt;br /&gt; 00001101&lt;br /&gt;+ 11100011&lt;br /&gt;----------&lt;br /&gt; 01100101&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;                 &lt;p&gt;&lt;span style="font-size:130%;"&gt;Because of this mathematical arrangement, simultaneous single-bit                  inversions could occur in each of any number of the "columns."                  At least one bit of the checksum will always be affected. No matter                  how the inversions occur, at least the lowest-order column with                  an error will alter the checksum. This is an important point,                  because it helps us to understand the broader class of errors                  that can be detected by this type of checksum. I'll say it again:                  no matter how the inversions occur, at least the lowest order                  column with an error will alter the checksum, which means that                  two or more bit inversions in higher-order columns may cancel                  each other out. As long as the lowest-order column with an error                  has only one, it doesn't matter what other errors may be hidden                  within the message. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Now let's step back for a minute and talk about errors more formally.                  What exactly does a transmission error look like? Well, the first                  and most obvious type of error is a single bit that is inverted.                  That happens sometimes and is easy to detect (even a parity bit                  will do the job). Other times, bit inversions are part of an error                  burst. Not all of the bits within an error burst must be inverted.                  The defining characteristic is simply an inverted bit on each                  end. So an error burst may be 200 bits long, but contain just                  two inverted bits--one at each end. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A sum-of-bytes checksum will detect the vast majority of error                  bursts, no matter what their length. However, describing exactly                  which ones is generally difficult. Only one class of error bursts                  is always detectable: those of length eight bits or less. As long                  as the two inverted bits that bound the error burst have no more                  than six bits between them, the error will always be detected                  by this algorithm. That's because our previous requirement for                  error detection--that the lowest-order column with an error have                  only one error--is always met when the length of the error burst                  is no longer than the width of the checksum. We can know with                  certainty that such errors will always be detected. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Of course, many longer error bursts will also be detected. The                  probability of detecting a random error burst longer than eight                  bits is 99.6%. Errors will only be overlooked if the modified                  message has exactly the same sum as the original one, for which                  there is a 2-8 chance. That's much better error detection than                  a simple parity bit, and for not too much more cost. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The sum-of-bytes algorithm becomes even more powerful when the                  width of the checksum is increased. In other words, increasing                  the number of bits in the checksum causes it to detect even more                  types of errors. A 16-bit sum-of-words checksum will detect all                  single bit errors and all error bursts of length 16 bits or fewer.                  It will also detect 99.998% of longer error bursts. A 32-bit sum                  will detect even more errors. In practice, this increase in performance                  must be weighed against the increased cost of sending the extra                  checksum bits as part of every exchange of data. &lt;/span&gt;&lt;/p&gt;                 &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Internet checksum&lt;/span&gt;&lt;/h2&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Many protocol stacks include some sort of a checksum within each                  protocol layer. The TCP/IP suite of protocols is no exception                  in this regard. In addition to a checksum at the lowest layer                  (within Ethernet packets, for example), checksums also exist within                  each IP, UDP, and TCP header. Figure 1 shows what some of these                  headers look like in the case of some data sent via UDP/IP. Here                  the fields of the IP header are summed to generate the 16-bit                  IP checksum and the data, fields of the UDP header, and certain                  fields of the IP header are summed to generate the 16-bit UDP                  checksum. &lt;/span&gt;&lt;/p&gt;               &lt;p align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;img src="http://www.netrino.com/images/articles/InternetChecksum.gif" height="216" width="313" /&gt;&lt;/span&gt;                &lt;/p&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Figure 1. UDP and IP headers with checksum                  fields highlighted&lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;A function that calculates the IP header checksum is shown in                  Listing 3. This function can be used before sending an IP packet                  or immediately after receiving one. If the packet is about to                  be sent, the checksum field should be set to zero before calculating                  the checksum and filled with the returned value afterward. If                  the packet has just been received, the checksum routine is expected                  to return a value of 0xFFFF                 to indicate that the IP header was received correctly. This result                  is a property of the type of addition used to compute the IP checksum.                &lt;/span&gt;&lt;/p&gt;  &lt;pre&gt;&lt;span style="font-size:130%;"&gt;uint16_t&lt;br /&gt;NetIpChecksum(uint16_t const ipHeader[], int nWords)&lt;br /&gt;{&lt;br /&gt;   uint16_t  sum = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * IP headers always contain an even number of bytes.&lt;br /&gt;    */&lt;br /&gt;   while (nWords-- &gt; 0)&lt;br /&gt;   {&lt;br /&gt;       sum += *(ipHeader++);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Use carries to compute 1's complement sum.&lt;br /&gt;    */&lt;br /&gt;   sum = (sum &gt;&gt; 16) + (sum &amp;amp; 0xFFFF);&lt;br /&gt;   sum += sum &gt;&gt; 16;&lt;br /&gt;&lt;br /&gt;   /*&lt;br /&gt;    * Return the inverted 16-bit result.&lt;br /&gt;    */&lt;br /&gt;   return ((unsigned short) ~sum);&lt;br /&gt;&lt;br /&gt;}   /* NetIpChecksum() */&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;               &lt;p class="caption"&gt;&lt;span style="font-size:130%;"&gt;Listing 3. IP header checksum calculation&lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;The IP header to be checksummed should be passed to NetIpChecksum()                 as an array of 16-bit words. Since the length of an IP header                  is always a multiple of four bytes, it is sufficient to provide                  the header length as a number of 16-bit words. The checksum is                  then computed by the function and returned to the caller for insertion                  into the header for validation of the header contents. &lt;/span&gt;&lt;/p&gt;                &lt;p&gt;&lt;span style="font-size:130%;"&gt;When you first look at this function, you may be overcome with                  a feeling of deja vu. The IP checksum algorithm begins                  in much the same way as the sum-of-bytes algorithm I discussed                  earlier. However, this algorithm is actually different. First,                  of course, we're computing a 16-bit checksum instead of an eight-bit                  one, so we're summing words rather than bytes. That difference                  is obvious. Less obvious is that we're actually computing a ones                  complement sum. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Recall that most computers store integers in a twos complement                  representation. Simply adding two integers, as we did in the previous                  algorithm, will therefore result in a twos complement sum. In                  order to compute the ones complement sum, we need to perform our                  addition with "end around carry." This means that carries out                  of the most significant bit (MSB) are not discarded, as they were                  previously. Instead, carries are added back into the checksum                  at the least significant bit (LSB). This could be done after each                  addition, but testing for a carry after each addition is expensive                  in C. A faster way is to let the carries accumulate in the upper                  half of a 32-bit accumulator. Once the sum-of-words is complete,                  the upper half of the 32-bit accumulator is turned into a 16-bit                  value and added to the 16-bit twos complement sum (the lower half).                  One final carry is possible at that point, and must be included                  in the final sum. The IP checksum is the inverted ones complement                  sum of all of the words in the IP header. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;For checksum purposes, ones complement arithmetic has an important                  advantage over twos complement arithmetic. Recall that the biggest                  weakness of a parity bit is that it can't detect a pair of bit                  errors or any even number of errors, for that matter. A twos complement                  sum suffers from a similar weakness. Only one of the bits in the                  sum (the MSB) is affected by changes in the most significant of                  the 16 columns. If an even number of bit errors occurs within                  that column, the checksum will appear to be correct and the error                  will not be detected. A ones complement sum does not suffer this                  weakness. &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;Because carries out of the MSB are added back into the LSB during                  a ones complement sum, errors in any one column of the data will                  be reflected in more than one bit of the checksum. So a ones complement                  sum is a stronger checksum (for example, will detect more errors)                  than a twos complement sum, and only slightly more expensive.                  Hence, it is chosen for use in a lot of different situations.                &lt;/span&gt;&lt;/p&gt;               &lt;p&gt;&lt;span style="font-size:130%;"&gt;The checksums within the UDP and TCP headers are computed in                  exactly the same way as the IP checksum. In fact, the only major                  difference is the set of words over which the sum is calculated.                  (A minor difference is that UDP checksums are optional.) In both                  cases, these layer 4 protocols include the message, their own                  header fields, and a few important fields of the IP header in                  the checksum calculation. The inclusion of some IP header fields                  in the UDP and TCP checksums is one of the biggest reasons that                  these layers of the protocol stack cannot be completely separated                  from the IP layer in a software implementation. The reason that                  IP checksums include only the IP header is that many intermediate                  computers must validate, read, and modify the contents of the                  IP header as a packet travels from its source to the destination.                  By reducing the number of words involved in the calculation, the                  speed with which all IP packets move across the Internet is improved.                  Including a larger set of words in the UDP and TCP checksums does                  not slow down communications; rather, it increases the likelihood                  that the message received is the same as the message sent. &lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-5317012962813000083?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/5317012962813000083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=5317012962813000083' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/5317012962813000083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/5317012962813000083'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/06/additive-checksums.html' title='Additive Checksums'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-7209851303295628505</id><published>2008-06-04T22:54:00.000-07:00</published><updated>2008-06-04T22:59:06.697-07:00</updated><title type='text'>Talking to Device Files (writes and IOCTLs)</title><content type='html'>&lt;h1 style="font-weight: normal;" class="SECT1"&gt;&lt;span&gt;&lt;span style="color:#000000;"&gt;&lt;pre class="PROGRAMLISTING"&gt;Device files are supposed to represent physical devices. Most physical devices are used for output as well as input, so there has to be some mechanism for device drivers in the kernel to get the output to send to the device from processes. This is done by opening the device file for output and writing to it, just like writing to a file. In the following example, this is implemented by device_write.&lt;br /&gt;&lt;br /&gt;This is not always enough. Imagine you had a serial port connected to a modem (even if you have an internal modem, it is still implemented from the CPU's perspective as a serial port connected to a modem, so you don't have to tax your imagination too hard). The natural thing to do would be to use the device file to write things to the modem (either modem commands or data to be sent through the phone line) and read things from the modem (either responses for commands or the data received through the phone line). However, this leaves open the question of what to do when you need to talk to the serial port itself, for example to send the rate at which data is sent and received.&lt;br /&gt;&lt;br /&gt;The answer in Unix is to use a special function called ioctl (short for Input Output ConTroL). Every device can have its own ioctl commands, which can be read ioctl's (to send information from a process to the kernel), write ioctl's (to return information to a process), [1] both or neither. The ioctl function is called with three parameters: the file descriptor of the appropriate device file, the ioctl number, and a parameter, which is of type long so you can use a cast to use it to pass anything. [2]&lt;br /&gt;&lt;br /&gt;The ioctl number encodes the major device number, the type of the ioctl, the command, and the type of the parameter. This ioctl number is usually created by a macro call (_IO, _IOR, _IOW or _IOWR --- depending on the type) in a header file. This header file should then be included both by the programs which will use ioctl (so they can generate the appropriate ioctl's) and by the kernel module (so it can understand it). In the example below, the header file is chardev.h and the program which uses it is ioctl.c.&lt;br /&gt;&lt;br /&gt;If you want to use ioctls in your own kernel modules, it is best to receive an official ioctl assignment, so if you accidentally get somebody else's ioctls, or if they get yours, you'll know something is wrong. For more information, consult the kernel source tree at Documentation/ioctl-number.txt.&lt;br /&gt;&lt;br /&gt;Example 7-1. chardev.c&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;*  chardev.c - Create an input/output character device&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;#include "linux/kernel.h" /* We're doing kernel work */&lt;br /&gt;#include "linux/module.h" /* Specifically, a module */&lt;br /&gt;#include "linux/fs.h"&lt;br /&gt;#include "asm/uaccess.h" /* for get_user and put_user */&lt;br /&gt;&lt;br /&gt;#include "chardev.h"&lt;br /&gt;#define SUCCESS 0&lt;br /&gt;#define DEVICE_NAME "char_dev"&lt;br /&gt;#define BUF_LEN 80&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Is the device open right now? Used to prevent&lt;br /&gt;* concurent access into the same device&lt;br /&gt;*/&lt;br /&gt;static int Device_Open = 0;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* The message the device will give when asked&lt;br /&gt;*/&lt;br /&gt;static char Message[BUF_LEN];&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* How far did the process reading the message get?&lt;br /&gt;* Useful if the message is larger than the size of the&lt;br /&gt;* buffer we get to fill in device_read.&lt;br /&gt;*/&lt;br /&gt;static char *Message_Ptr;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* This is called whenever a process attempts to open the device file&lt;br /&gt;*/&lt;br /&gt;static int device_open(struct inode *inode, struct file *file)&lt;br /&gt;{&lt;br /&gt;#ifdef DEBUG&lt;br /&gt; printk(KERN_INFO "device_open(%p)\n", file);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * We don't want to talk to two processes at the same time&lt;br /&gt;  */&lt;br /&gt; if (Device_Open)&lt;br /&gt;  return -EBUSY;&lt;br /&gt;&lt;br /&gt; Device_Open++;&lt;br /&gt; /*&lt;br /&gt;  * Initialize the message&lt;br /&gt;  */&lt;br /&gt; Message_Ptr = Message;&lt;br /&gt; try_module_get(THIS_MODULE);&lt;br /&gt; return SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int device_release(struct inode *inode, struct file *file)&lt;br /&gt;{&lt;br /&gt;#ifdef DEBUG&lt;br /&gt; printk(KERN_INFO "device_release(%p,%p)\n", inode, file);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * We're now ready for our next caller&lt;br /&gt;  */&lt;br /&gt; Device_Open--;&lt;br /&gt;&lt;br /&gt; module_put(THIS_MODULE);&lt;br /&gt; return SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* This function is called whenever a process which has already opened the&lt;br /&gt;* device file attempts to read from it.&lt;br /&gt;*/&lt;br /&gt;static ssize_t device_read(struct file *file, /* see include/linux/fs.h   */&lt;br /&gt;      char __user * buffer, /* buffer to be&lt;br /&gt;        * filled with data */&lt;br /&gt;      size_t length, /* length of the buffer     */&lt;br /&gt;      loff_t * offset)&lt;br /&gt;{&lt;br /&gt; /*&lt;br /&gt;  * Number of bytes actually written to the buffer&lt;br /&gt;  */&lt;br /&gt; int bytes_read = 0;&lt;br /&gt;&lt;br /&gt;#ifdef DEBUG&lt;br /&gt; printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * If we're at the end of the message, return 0&lt;br /&gt;  * (which signifies end of file)&lt;br /&gt;  */&lt;br /&gt; if (*Message_Ptr == 0)&lt;br /&gt;  return 0;&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Actually put the data into the buffer&lt;br /&gt;  */&lt;br /&gt; while (length &amp;amp;&amp;amp; *Message_Ptr) {&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * Because the buffer is in the user data segment,&lt;br /&gt;   * not the kernel data segment, assignment wouldn't&lt;br /&gt;   * work. Instead, we have to use put_user which&lt;br /&gt;   * copies data from the kernel data segment to the&lt;br /&gt;   * user data segment.&lt;br /&gt;   */&lt;br /&gt;  put_user(*(Message_Ptr++), buffer++);&lt;br /&gt;  length--;&lt;br /&gt;  bytes_read++;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#ifdef DEBUG&lt;br /&gt; printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Read functions are supposed to return the number&lt;br /&gt;  * of bytes actually inserted into the buffer&lt;br /&gt;  */&lt;br /&gt; return bytes_read;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* This function is called when somebody tries to&lt;br /&gt;* write into our device file.&lt;br /&gt;*/&lt;br /&gt;static ssize_t&lt;br /&gt;device_write(struct file *file,&lt;br /&gt;      const char __user * buffer, size_t length, loff_t * offset)&lt;br /&gt;{&lt;br /&gt; int i;&lt;br /&gt;&lt;br /&gt;#ifdef DEBUG&lt;br /&gt; printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt; for (i = 0; i " length &amp;amp;&amp;amp; i " BUF_LEN; i++)&lt;br /&gt;  get_user(Message[i], buffer + i);&lt;br /&gt;&lt;br /&gt; Message_Ptr = Message;&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Again, return the number of input characters used&lt;br /&gt;  */&lt;br /&gt; return i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* This function is called whenever a process tries to do an ioctl on our&lt;br /&gt;* device file. We get two extra parameters (additional to the inode and file&lt;br /&gt;* structures, which all device functions get): the number of the ioctl called&lt;br /&gt;* and the parameter given to the ioctl function.&lt;br /&gt;*&lt;br /&gt;* If the ioctl is write or read/write (meaning output is returned to the&lt;br /&gt;* calling process), the ioctl call returns the output of this function.&lt;br /&gt;*&lt;br /&gt;*/&lt;br /&gt;int device_ioctl(struct inode *inode, /* see include/linux/fs.h */&lt;br /&gt;   struct file *file, /* ditto */&lt;br /&gt;   unsigned int ioctl_num, /* number and param for ioctl */&lt;br /&gt;   unsigned long ioctl_param)&lt;br /&gt;{&lt;br /&gt; int i;&lt;br /&gt; char *temp;&lt;br /&gt; char ch;&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Switch according to the ioctl called&lt;br /&gt;  */&lt;br /&gt; switch (ioctl_num) {&lt;br /&gt; case IOCTL_SET_MSG:&lt;br /&gt;  /*&lt;br /&gt;   * Receive a pointer to a message (in user space) and set that&lt;br /&gt;   * to be the device's message.  Get the parameter given to&lt;br /&gt;   * ioctl by the process.&lt;br /&gt;   */&lt;br /&gt;  temp = (char *)ioctl_param;&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * Find the length of the message&lt;br /&gt;   */&lt;br /&gt;  get_user(ch, temp);&lt;br /&gt;  for (i = 0; ch &amp;amp;&amp;amp; i " BUF_LEN; i++, temp++)&lt;br /&gt;   get_user(ch, temp);&lt;br /&gt;&lt;br /&gt;  device_write(file, (char *)ioctl_param, i, 0);&lt;br /&gt;  break;&lt;br /&gt;&lt;br /&gt; case IOCTL_GET_MSG:&lt;br /&gt;  /*&lt;br /&gt;   * Give the current message to the calling process -&lt;br /&gt;   * the parameter we got is a pointer, fill it.&lt;br /&gt;   */&lt;br /&gt;  i = device_read(file, (char *)ioctl_param, 99, 0);&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * Put a zero at the end of the buffer, so it will be&lt;br /&gt;   * properly terminated&lt;br /&gt;   */&lt;br /&gt;  put_user('\0', (char *)ioctl_param + i);&lt;br /&gt;  break;&lt;br /&gt;&lt;br /&gt; case IOCTL_GET_NTH_BYTE:&lt;br /&gt;  /*&lt;br /&gt;   * This ioctl is both input (ioctl_param) and&lt;br /&gt;   * output (the return value of this function)&lt;br /&gt;   */&lt;br /&gt;  return Message[ioctl_param];&lt;br /&gt;  break;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Module Declarations */&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* This structure will hold the functions to be called&lt;br /&gt;* when a process does something to the device we&lt;br /&gt;* created. Since a pointer to this structure is kept in&lt;br /&gt;* the devices table, it can't be local to&lt;br /&gt;* init_module. NULL is for unimplemented functions.&lt;br /&gt;*/&lt;br /&gt;struct file_operations Fops = {&lt;br /&gt; .read = device_read,&lt;br /&gt; .write = device_write,&lt;br /&gt; .ioctl = device_ioctl,&lt;br /&gt; .open = device_open,&lt;br /&gt; .release = device_release, /* a.k.a. close */&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Initialize the module - Register the character device&lt;br /&gt;*/&lt;br /&gt;int init_module()&lt;br /&gt;{&lt;br /&gt; int ret_val;&lt;br /&gt; /*&lt;br /&gt;  * Register the character device (atleast try)&lt;br /&gt;  */&lt;br /&gt; ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &amp;amp;Fops);&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Negative values signify an error&lt;br /&gt;  */&lt;br /&gt; if (ret_val " 0) {&lt;br /&gt;  printk(KERN_ALERT "%s failed with %d\n",&lt;br /&gt;         "Sorry, registering the character device ", ret_val);&lt;br /&gt;  return ret_val;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; printk(KERN_INFO "%s The major device number is %d.\n",&lt;br /&gt;        "Registeration is a success", MAJOR_NUM);&lt;br /&gt; printk(KERN_INFO "If you want to talk to the device driver,\n");&lt;br /&gt; printk(KERN_INFO "you'll have to create a device file. \n");&lt;br /&gt; printk(KERN_INFO "We suggest you use:\n");&lt;br /&gt; printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);&lt;br /&gt; printk(KERN_INFO "The device file name is important, because\n");&lt;br /&gt; printk(KERN_INFO "the ioctl program assumes that's the\n");&lt;br /&gt; printk(KERN_INFO "file you'll use.\n");&lt;br /&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Cleanup - unregister the appropriate file from /proc&lt;br /&gt;*/&lt;br /&gt;void cleanup_module()&lt;br /&gt;{&lt;br /&gt; int ret;&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Unregister the device&lt;br /&gt;  */&lt;br /&gt; ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * If there's an error, report it&lt;br /&gt;  */&lt;br /&gt; if (ret " 0)&lt;br /&gt;  printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Example 7-2. chardev.h&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;*  chardev.h - the header file with the ioctl definitions.&lt;br /&gt;*&lt;br /&gt;*  The declarations here have to be in a header file, because&lt;br /&gt;*  they need to be known both to the kernel module&lt;br /&gt;*  (in chardev.c) and the process calling ioctl (ioctl.c)&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;#ifndef CHARDEV_H&lt;br /&gt;#define CHARDEV_H&lt;br /&gt;&lt;br /&gt;#include "linux/ioctl.h"&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* The major device number. We can't rely on dynamic&lt;br /&gt;* registration any more, because ioctls need to know&lt;br /&gt;* it.&lt;br /&gt;*/&lt;br /&gt;#define MAJOR_NUM 100&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Set the message of the device driver&lt;br /&gt;*/&lt;br /&gt;#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)&lt;br /&gt;/*&lt;br /&gt;* _IOR means that we're creating an ioctl command&lt;br /&gt;* number for passing information from a user process&lt;br /&gt;* to the kernel module.&lt;br /&gt;*&lt;br /&gt;* The first arguments, MAJOR_NUM, is the major device&lt;br /&gt;* number we're using.&lt;br /&gt;*&lt;br /&gt;* The second argument is the number of the command&lt;br /&gt;* (there could be several with different meanings).&lt;br /&gt;*&lt;br /&gt;* The third argument is the type we want to get from&lt;br /&gt;* the process to the kernel.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Get the message of the device driver&lt;br /&gt;*/&lt;br /&gt;#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)&lt;br /&gt;/*&lt;br /&gt;* This IOCTL is used for output, to get the message&lt;br /&gt;* of the device driver. However, we still need the&lt;br /&gt;* buffer to place the message in to be input,&lt;br /&gt;* as it is allocated by the process.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Get the n'th byte of the message&lt;br /&gt;*/&lt;br /&gt;#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)&lt;br /&gt;/*&lt;br /&gt;* The IOCTL is used for both input and output. It&lt;br /&gt;* receives from the user a number, n, and returns&lt;br /&gt;* Message[n].&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* The name of the device file&lt;br /&gt;*/&lt;br /&gt;#define DEVICE_FILE_NAME "char_dev"&lt;br /&gt;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;Example 7-3. ioctl.c&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;*  ioctl.c - the process to use ioctl's to control the kernel module&lt;br /&gt;*&lt;br /&gt;*  Until now we could have used cat for input and output.  But now&lt;br /&gt;*  we need to do ioctl's, which require writing our own process.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* device specifics, such as ioctl numbers and the&lt;br /&gt;* major device file.&lt;br /&gt;*/&lt;br /&gt;#include "chardev.h"&lt;br /&gt;&lt;br /&gt;#include "stdio.h"&lt;br /&gt;#include "stdlib.h"&lt;br /&gt;#include "fcntl.h"  /* open */&lt;br /&gt;#include "unistd.h"  /* exit */&lt;br /&gt;#include "sys/ioctl.h"  /* ioctl */&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Functions for the ioctl calls&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;ioctl_set_msg(int file_desc, char *message)&lt;br /&gt;{&lt;br /&gt; int ret_val;&lt;br /&gt;&lt;br /&gt; ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);&lt;br /&gt;&lt;br /&gt; if (ret_val " 0) {&lt;br /&gt;  printf("ioctl_set_msg failed:%d\n", ret_val);&lt;br /&gt;  exit(-1);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ioctl_get_msg(int file_desc)&lt;br /&gt;{&lt;br /&gt; int ret_val;&lt;br /&gt; char message[100];&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * Warning - this is dangerous because we don't tell&lt;br /&gt;  * the kernel how far it's allowed to write, so it&lt;br /&gt;  * might overflow the buffer. In a real production&lt;br /&gt;  * program, we would have used two ioctls - one to tell&lt;br /&gt;  * the kernel the buffer length and another to give&lt;br /&gt;  * it the buffer to fill&lt;br /&gt;  */&lt;br /&gt; ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);&lt;br /&gt;&lt;br /&gt; if (ret_val " 0) {&lt;br /&gt;  printf("ioctl_get_msg failed:%d\n", ret_val);&lt;br /&gt;  exit(-1);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; printf("get_msg message:%s\n", message);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ioctl_get_nth_byte(int file_desc)&lt;br /&gt;{&lt;br /&gt; int i;&lt;br /&gt; char c;&lt;br /&gt;&lt;br /&gt; printf("get_nth_byte message:");&lt;br /&gt;&lt;br /&gt; i = 0;&lt;br /&gt; do {&lt;br /&gt;  c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);&lt;br /&gt;&lt;br /&gt;  if (c " 0) {&lt;br /&gt;   printf&lt;br /&gt;       ("ioctl_get_nth_byte failed at the %d'th byte:\n",&lt;br /&gt;        i);&lt;br /&gt;   exit(-1);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  putchar(c);&lt;br /&gt; } while (c != 0);&lt;br /&gt; putchar('\n');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Main - Call the ioctl functions&lt;br /&gt;*/&lt;br /&gt;main()&lt;br /&gt;{&lt;br /&gt; int file_desc, ret_val;&lt;br /&gt; char *msg = "Message passed by ioctl\n";&lt;br /&gt;&lt;br /&gt; file_desc = open(DEVICE_FILE_NAME, 0);&lt;br /&gt; if (file_desc " 0) {&lt;br /&gt;  printf("Can't open device file: %s\n", DEVICE_FILE_NAME);&lt;br /&gt;  exit(-1);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; ioctl_get_nth_byte(file_desc);&lt;br /&gt; ioctl_get_msg(file_desc);&lt;br /&gt; ioctl_set_msg(file_desc, msg);&lt;br /&gt;&lt;br /&gt; close(file_desc);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-7209851303295628505?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/7209851303295628505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=7209851303295628505' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/7209851303295628505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/7209851303295628505'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/06/talking-to-device-files-writes-and.html' title='Talking to Device Files (writes and IOCTLs)'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-8688519715257884867</id><published>2008-05-29T02:40:00.000-07:00</published><updated>2008-05-29T02:44:33.626-07:00</updated><title type='text'>Serial Programming Guide for POSIX Operating Systems</title><content type='html'>&lt;h1&gt;Serial Programming Guide for POSIX Operating Systems&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;h1&gt;&lt;center&gt;&lt;a name="CONTENTS"&gt;Table of Contents&lt;/a&gt;&lt;/center&gt;&lt;/h1&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Chapter 1, Basics of Serial Communications&lt;/b&gt;&lt;ul&gt;&lt;li&gt;What Are Serial Communications?&lt;/li&gt;&lt;li&gt;What Is RS-232?&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Signal Definitions&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Asynchronous Communications&lt;/li&gt;&lt;ul&gt;&lt;li&gt;What Are Full Duplex and Half Duplex?&lt;/li&gt;&lt;li&gt;Flow Control&lt;/li&gt;&lt;li&gt;What Is a Break?&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Synchronous Communications&lt;/li&gt;&lt;li&gt;Accessing Serial Ports&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Serial Port Files&lt;/li&gt;&lt;li&gt;Opening a Serial Port&lt;/li&gt;&lt;li&gt;Writing Data to the Port&lt;/li&gt;&lt;li&gt;Reading Data from the Port&lt;/li&gt;&lt;li&gt;Closing a Serial Port&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;b&gt;Chapter 2, Configuring the Serial Port&lt;/b&gt;&lt;ul&gt;&lt;li&gt;The POSIX Terminal Interface&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Control Options&lt;/li&gt;&lt;li&gt;Local Options&lt;/li&gt;&lt;li&gt;Input Options&lt;/li&gt;&lt;li&gt;Output Options&lt;/li&gt;&lt;li&gt;Control Characters&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;b&gt;Chapter 3, MODEM Communications&lt;/b&gt;&lt;ul&gt;&lt;li&gt;What Is a MODEM?&lt;/li&gt;&lt;li&gt;Communicating With a MODEM&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Standard MODEM Commands&lt;/li&gt;&lt;li&gt;Common MODEM Communication Problems&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;b&gt;Chapter 4, Advanced Serial Programming&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Serial Port IOCTLs&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Getting the Control Signals&lt;/li&gt;&lt;li&gt;Setting the Control Signals&lt;/li&gt;&lt;li&gt;Getting the Number of Bytes Available&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Selecting Input from a Serial Port&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The SELECT System Call&lt;/li&gt;&lt;li&gt;Using the SELECT System Call&lt;/li&gt;&lt;li&gt;Using SELECT with the X Intrinsics Library&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;b&gt;Appendix A, Pinouts&lt;/b&gt;&lt;ul&gt;&lt;li&gt;RS-232 Pinouts&lt;/li&gt;&lt;li&gt;RS-422 Pinouts&lt;/li&gt;&lt;li&gt;RS-574 (IBM PC/AT) Pinouts&lt;/li&gt;&lt;li&gt;SGI Pinouts&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Appendix B, ASCII Control Codes&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Control Codes&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="1"&gt;Introduction&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The Serial Programming Guide for POSIX Operating Systems will teach  you how to successfully, efficiently, and portably program the serial  ports on your UNIX® workstation or PC. Each chapter provides  programming examples that use the POSIX (Portable Standard for UNIX)  terminal control functions and should work with very few modifications  under IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux®, and most  other UNIX operating systems. The biggest difference between operating  systems that you will find is the filenames used for serial port device  and lock files. &lt;/p&gt;&lt;p&gt;This guide is organized into the following chapters and appendices: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Chapter 1, Basics of Serial Programming&lt;/li&gt;&lt;li&gt;Chapter 2, Configuring the Serial Port&lt;/li&gt;&lt;li&gt;Chapter 3, Talking to MODEMs&lt;/li&gt;&lt;li&gt;Chapter 4, Advanced Serial Programming&lt;/li&gt;&lt;li&gt;Appendix A, RS-232 Pinouts&lt;/li&gt;&lt;li&gt;Appendix B, ASCII Control Codes&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="basics"&gt;Chapter 1, Basics of Serial  Communications&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This chapter introduces serial communications, RS-232 and other  standards that are used on most computers as well as how to access a  serial port from a C program. &lt;/p&gt;&lt;h2&gt;&lt;a name="2_1"&gt;What Are Serial Communications?&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Computers transfer information (data) one or more bits at a time.  Serial refers to the transfer of data one bit at a time. Serial  communications include most network devices, keyboards, mice, MODEMs,  and terminals. &lt;/p&gt;&lt;p&gt;When doing serial communications each word (i.e. byte or character)  of data you send or receive is sent one bit at a time. Each bit is  either &lt;i&gt;on&lt;/i&gt; or &lt;i&gt;off.&lt;/i&gt; The terms you'll hear sometimes are &lt;i&gt; mark&lt;/i&gt; for the &lt;i&gt;on&lt;/i&gt; state and &lt;i&gt;space&lt;/i&gt; for the &lt;i&gt;off&lt;/i&gt;  state. &lt;/p&gt;&lt;p&gt;The speed of the serial data is most often expressed as  bits-per-second ("bps") or baudot rate ("baud"). This just represents  the number of ones and zeroes that can be sent in one second. Back at  the dawn of the computer age, 300 baud was considered fast, but today  computers can handle RS-232 speeds as high as 430,800 baud! When the  baud rate exceeds 1,000, you'll usually see the rate shown in &lt;i&gt;kilo&lt;/i&gt; baud, or kbps (e.g. 9.6k, 19.2k, etc). For rates above 1,000,000 that  rate is shown in &lt;i&gt;mega&lt;/i&gt;baud, or Mbps (e.g. 1.5Mbps). &lt;/p&gt;&lt;p&gt;When referring to serial devices or ports, they are either labeled  as &lt;i&gt;Data Communications Equipment&lt;/i&gt; ("DCE") or &lt;i&gt;Data Terminal  Equipment&lt;/i&gt; ("DTE"). The difference between these is simple - every  signal pair, like transmit and receive, is swapped. When connecting two  DTE or two DCE interfaces together, a serial &lt;i&gt;null-MODEM&lt;/i&gt; cable or  adapter is used that swaps the signal pairs. &lt;/p&gt;&lt;h2&gt;&lt;a name="2_2"&gt;What Is RS-232?&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;RS-232 is a standard electrical interface for serial communications  defined by the Electronic Industries  Association ("EIA"). RS-232 actually comes in 3 different flavors  (A, B, and C) with each one defining a different voltage range for the &lt;i&gt; on&lt;/i&gt; and &lt;i&gt;off&lt;/i&gt; levels. The most commonly used variety is  RS-232C, which defines a mark (on) bit as a voltage between -3V and  -12V and a space (off) bit as a voltage between +3V and +12V. The  RS-232C specification says these signals can go about 25 feet (8m)  before they become unusable. You can usually send signals a bit farther  than this as long as the baud is low enough. &lt;/p&gt;&lt;p&gt;Besides wires for incoming and outgoing data, there are others that  provide timing, status, and handshaking:  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="80%"&gt;&lt;caption align="CENTER"&gt;Table 1 - RS-232 Pin  Assignments&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt; Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt; Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Earth Ground&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;b&gt;DSR&lt;/b&gt; - Data Set  Ready&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;Secondary RXD&lt;/td&gt;&lt;td&gt; 21&lt;/td&gt;&lt;td&gt;Signal Quality Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt;  - Logic Ground&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;Secondary DCD&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt; Receiver Clock&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;Ring Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;RXD&lt;/b&gt; - Received Data&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD&lt;/b&gt;  - Data Carrier Detect&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;Secondary CTS&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt; Unassigned&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;Data Rate Select&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS&lt;/b&gt; - Request To Send&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt; Reserved&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;Secondary TXD&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;Secondary  RTS&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;Transmit Clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS&lt;/b&gt; - Clear To Send&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Reserved&lt;/td&gt;&lt;td&gt; 15&lt;/td&gt;&lt;td&gt;Transmit Clock&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR&lt;/b&gt; - Data Terminal  Ready&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;p&gt;Two standards for serial interfaces you may also see are RS-422 and  RS-574. RS-422 uses lower voltages and &lt;i&gt;differential&lt;/i&gt; signals to  allow cable lengths up to about 1000ft (300m). RS-574 defines the 9-pin  PC serial connector and voltages. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_2_1"&gt;Signal Definitions&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The RS-232 standard defines some 18 different signals for serial  communications. Of these, only six are generally available in the UNIX  environment. &lt;/p&gt;&lt;h4&gt;GND - Logic Ground&lt;/h4&gt;&lt;p&gt;Technically the logic ground is not a signal, but without it none of  the other signals will operate. Basically, the logic ground acts as a  reference voltage so that the electronics know which voltages are  positive or negative. &lt;/p&gt;&lt;h4&gt;TXD - Transmitted Data&lt;/h4&gt;&lt;p&gt;The TXD signal carries data transmitted from your workstation to the  computer or device on the other end (like a MODEM). A mark voltage is  interpreted as a value of 1, while a space voltage is interpreted as a  value of 0. &lt;/p&gt;&lt;h4&gt;RXD - Received Data&lt;/h4&gt;&lt;p&gt;The RXD signal carries data transmitted from the computer or device  on the other end to your workstation. Like TXD, mark and space voltages  are interpreted as 1 and 0, respectively. &lt;/p&gt;&lt;h4&gt;DCD - Data Carrier Detect&lt;/h4&gt;&lt;p&gt;The DCD signal is received from the computer or device on the other  end of your serial cable. A space voltage on this signal line indicates  that the computer or device is currently connected or on line. DCD is  not always used or available. &lt;/p&gt;&lt;h4&gt;DTR - Data Terminal Ready&lt;/h4&gt;&lt;p&gt;The DTR signal is generated by your workstation and tells the  computer or device on the other end that you are ready (a space  voltage) or not-ready (a mark voltage). DTR is usually enabled  automatically whenever you open the serial interface on the  workstation. &lt;/p&gt;&lt;h4&gt;CTS - Clear To Send&lt;/h4&gt;&lt;p&gt;The CTS signal is received from the other end of the serial cable. A  space voltage indicates that is alright to send more serial data from  your workstation. &lt;/p&gt;&lt;p&gt;CTS is usually used to regulate the flow of serial data from your  workstation to the other end. &lt;/p&gt;&lt;h4&gt;RTS - Request To Send&lt;/h4&gt;&lt;p&gt;The RTS signal is set to the &lt;i&gt;space&lt;/i&gt; voltage by your  workstation to indicate that more data is ready to be sent. &lt;/p&gt;&lt;p&gt;Like CTS, RTS helps to regulate the flow of data between your  workstation and the computer or device on the other end of the serial  cable. Most workstations leave this signal set to the space voltage all  the time. &lt;/p&gt;&lt;h2&gt;&lt;a name="2_3"&gt;Asynchronous Communications&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;For the computer to understand the serial data coming into it, it  needs some way to determine where one character ends and the next  begins. This guide deals exclusively with &lt;i&gt;asynchronous&lt;/i&gt; serial  data. &lt;/p&gt;&lt;p&gt;In asynchronous mode the serial data line stays in the mark (1)  state until a character is transmitted. A &lt;i&gt;start&lt;/i&gt; bit preceeds  each character and is followed immediately by each bit in the  character, an optional parity bit, and one or more &lt;i&gt;stop&lt;/i&gt; bits.  The start bit is always a space (0) and tells the computer that new  serial data is available. Data can be sent or received at any time,  thus the name asynchronous.  &lt;!-- PAGE BREAK ----&gt; &lt;/p&gt;&lt;p align="center"&gt;Figure 1 - Asynchronous Data Transmission&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/async.gif" width="90%" /&gt;&lt;/p&gt;&lt;p&gt;The optional parity bit is a simple sum of the data bits indicating  whether or not the data contains an even or odd number of 1 bits. With &lt;i&gt; even parity&lt;/i&gt;, the parity bit is 0 if there is an even number of 1's  in the character. With &lt;i&gt;odd parity&lt;/i&gt;, the parity bit is 0 if there  is an odd number of 1's in the data. You may also hear the terms &lt;i&gt; space parity&lt;/i&gt;, &lt;i&gt;mark parity&lt;/i&gt;, and &lt;i&gt;no parity&lt;/i&gt;. Space  parity means that the parity bit is always 0, while mark parity means  the bit is always 1. No parity means that no parity bit is present or  transmitted. &lt;/p&gt;&lt;p&gt;The remaining bits are called stop bits. There can be 1, 1.5, or 2  stop bits between characters and they always have a value of 1. Stop  bits traditionally were used to give the computer time to process the  previous character, but now only serve to synchronize the receiving  computer to the incoming characters. &lt;/p&gt;&lt;p&gt;Asynchronous data formats are usually expressed as "8N1", "7E1", and  so forth. These stand for "8 data bits, no parity, 1 stop bit" and "7  data bits, even parity, 1 stop bit" respectively. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_3_1"&gt;What Are Full Duplex and Half Duplex?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;i&gt;Full duplex&lt;/i&gt; means that the computer can send and receive data  simultaneously - there are two separate data channels (one coming in,  one going out). &lt;/p&gt;&lt;p&gt;&lt;i&gt;Half duplex&lt;/i&gt; means that the computer cannot send or receive  data at the same time. Usually this means there is only a single data  channel to talk over. This does not mean that any of the RS-232 signals  are not used. Rather, it usually means that the communications link  uses some standard other than RS-232 that does not support full duplex  operation. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_3_2"&gt;Flow Control&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;It is often necessary to regulate the flow of data when transferring  data between two serial interfaces. This can be due to limitations in  an intermediate serial communications link, one of the serial  interfaces, or some storage media. Two methods are commonly used for  asynchronous data. &lt;/p&gt;&lt;p&gt;The first method is often called "software" flow control and uses  special characters to start (XON or DC1, 021 octal) or stop (XOFF or  DC3, 023 octal) the flow of data. These characters are defined in the  American Standard Code for Information Interchange ("ASCII"). While  these codes are useful when transferring textual information, they  cannot be used when transferring other types of information without  special programming. &lt;/p&gt;&lt;p&gt;The second method is called "hardware" flow control and uses the  RS-232 CTS and RTS signals instead of special characters. The receiver  sets CTS to the space voltage when it is ready to receive more data and  to the mark voltage when it is not ready. Likewise, the sender sets RTS  to the space voltage when it is ready to send more data. Because  hardware flow control uses a separate set of signals, it is much faster  than software flow control which needs to send or receive multiple bits  of information to do the same thing. CTS/RTS flow control is not  supported by all hardware or operating systems. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_3_3"&gt;What Is a Break?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Normally a receive or transmit data signal stays at the mark voltage  until a new character is transferred. If the signal is dropped to the  space voltage for a long period of time, usually 1/4 to 1/2 second,  then a break condition is said to exist. &lt;/p&gt;&lt;p&gt;A break is sometimes used to reset a communications line or change  the operating mode of communications hardware like a MODEM.  Chapter 3, Talking to MODEMs covers these applications in more  depth. &lt;/p&gt;&lt;h2&gt;&lt;a name="2_4"&gt;Synchronous Communications&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Unlike asynchronous data, synchronous data appears as a constant  stream of bits. To read the data on the line, the computer must provide  or receive a common bit clock so that both the sender and receiver are  synchronized. &lt;/p&gt;&lt;p&gt;Even with this synchronization, the computer must mark the beginning  of the data somehow. The most common way of doing this is to use a data  packet protocol like Serial Data Link Control ("SDLC") or High-Speed  Data Link Control ("HDLC"). &lt;/p&gt;&lt;p&gt;Each protocol defines certain bit sequences to represent the  beginning and end of a data packet. Each also defines a bit sequence  that is used when there is no data. These bit sequences allow the  computer see the beginning of a data packet. &lt;/p&gt;&lt;p&gt;Because synchronous protocols do not use per-character  synchronization bits they typically provide at least a 25% improvement  in performance over asynchronous communications and are suitable for  remote networking and configurations with more than two serial  interfaces. &lt;/p&gt;&lt;p&gt;Despite the speed advantages of synchronous communications, most  RS-232 hardware does not support it due to the extra hardware and  software required. &lt;/p&gt;&lt;h2&gt;&lt;a name="2_5"&gt;Accessing Serial Ports&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Like all devices, UNIX provides access to serial ports via &lt;i&gt;device  files&lt;/i&gt;. To access a serial port you simply open the corresponding  device file. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_5_1"&gt;Serial Port Files&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Each serial port on a UNIX system has one or more device files  (files in the &lt;tt&gt;/dev&lt;/tt&gt; directory) associated with it:  &lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 2 - Serial Port Device  Files&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;System&lt;/th&gt;&lt;th&gt;Port 1&lt;/th&gt;&lt;th&gt;Port 2&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IRIX®&lt;/td&gt;&lt;td&gt;/dev/ttyf1&lt;/td&gt;&lt;td&gt;/dev/ttyf2&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;HP-UX&lt;/td&gt;&lt;td&gt;/dev/tty1p0&lt;/td&gt;&lt;td&gt;/dev/tty2p0&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Solaris®/SunOS®&lt;/td&gt;&lt;td&gt;/dev/ttya&lt;/td&gt;&lt;td&gt;/dev/ttyb&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Linux®&lt;/td&gt;&lt;td&gt;/dev/ttyS0&lt;/td&gt;&lt;td&gt;/dev/ttyS1&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;Digital UNIX®&lt;/td&gt;&lt;td&gt;/dev/tty01&lt;/td&gt;&lt;td&gt;/dev/tty02&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h3&gt;&lt;a name="2_5_2"&gt;Opening a Serial Port&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Since a serial port is a file, the &lt;i&gt;open(2)&lt;/i&gt; function is used  to access it. The one hitch with UNIX is that device files are usually  not accessable by normal users. Workarounds include changing the access  permissions to the file(s) in question, running your program as the  super-user (root), or making your program set-userid so that it runs as  the owner of the device file. &lt;/p&gt;&lt;p&gt;For now we'll assume that the file is accessable by all users. The  code to open serial port 1 on an &lt;code&gt;sgi&lt;/code&gt;® workstation running  IRIX is: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 1 - Opening a serial port. &lt;/p&gt;&lt;pre&gt;#include 'stdio.h'  /* Standard input/output definitions */&lt;br /&gt;#include 'string.h'  /* String function definitions */&lt;br /&gt;#include 'unistd.h'  /* UNIX standard function definitions */&lt;br /&gt;#include 'fcntl.h'   /* File control definitions */&lt;br /&gt;#include 'errno.h'   /* Error number definitions */&lt;br /&gt;#include 'termios.h' /* POSIX terminal control definitions */&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* 'open_port()' - Open serial port 1.&lt;br /&gt;*&lt;br /&gt;* Returns the file descriptor on success or -1 on error.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;open_port(void)&lt;br /&gt;{&lt;br /&gt; int fd; /* File descriptor for the port */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt; if (fd == -1)&lt;br /&gt; {&lt;br /&gt;  /*&lt;br /&gt;   * Could not open the port.&lt;br /&gt;   */&lt;br /&gt;&lt;br /&gt;   perror("open_port: Unable to open /dev/ttyf1 - ");&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt;   fcntl(fd, F_SETFL, 0);&lt;br /&gt;&lt;br /&gt; return (fd);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;Other systems would require the corresponding device file name, but  otherwise the code is the same. &lt;/p&gt;&lt;h4&gt;Open Options&lt;/h4&gt;&lt;p&gt;You'll notice that when we opened the device file we used two other  flags along with the read+write mode: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;O_NOCTTY&lt;/i&gt; flag tells UNIX that this program doesn't want  to be the "controlling terminal" for that port. If you don't specify  this then any input (such as keyboard abort signals and so forth) will  affect your process. Programs like &lt;i&gt;getty(1M/8)&lt;/i&gt; use this feature  when starting the login process, but normally a user program does not  want this behavior. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;O_NDELAY&lt;/i&gt; flag tells UNIX that this program doesn't care  what state the DCD signal line is in - whether the other end of the  port is up and running. If you do not specify this flag, your process  will be put to sleep until the DCD signal line is the space voltage. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_5_3"&gt;Writing Data to the Port&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Writing data to the port is easy - just use the &lt;i&gt;write(2)&lt;/i&gt;  system call to send data it: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;n = write(fd, "ATZ\r", 4);&lt;br /&gt;if (n &lt; 0)&lt;br /&gt; fputs("write() of 4 bytes failed!\n", stderr);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;write&lt;/i&gt; function returns the number of bytes sent or -1 if  an error occurred. Usually the only error you'll run into is &lt;i&gt;EIO&lt;/i&gt;  when a MODEM or data link drops the Data Carrier Detect (DCD) line.  This condition will persist until you close the port. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_5_4"&gt;Reading Data from the Port&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Reading data from a port is a little trickier. When you operate the  port in raw data mode, each &lt;i&gt;read(2)&lt;/i&gt; system call will return  however many characters are actually available in the serial input  buffers. If no characters are available, the call will block (wait)  until characters come in, an interval timer expires, or an error  occurs. The &lt;i&gt;read&lt;/i&gt; function can be made to return immediately by  doing the following: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;fcntl(fd, F_SETFL, FNDELAY);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;FNDELAY&lt;/i&gt; option causes the &lt;i&gt;read&lt;/i&gt; function to return  0 if no characters are available on the port. To restore normal  (blocking) behavior, call &lt;i&gt;fcntl()&lt;/i&gt; without the &lt;i&gt;FNDELAY&lt;/i&gt;  option: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;fcntl(fd, F_SETFL, 0);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;This is also used after opening a serial port with the O_NDELAY  option. &lt;/p&gt;&lt;h3&gt;&lt;a name="2_5_5"&gt;Closing a Serial Port&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;To close the serial port, just use the &lt;i&gt;close&lt;/i&gt; system call: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;close(fd);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;Closing a serial port will also usually set the DTR signal low which  causes most MODEMs to hang up. &lt;/p&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="config"&gt;Chapter 2, Configuring the Serial  Port&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This chapter discusses how to configure a serial port from C using  the POSIX termios interface. &lt;/p&gt;&lt;h2&gt;&lt;a name="3_1"&gt;The POSIX Terminal Interface&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Most systems support the POSIX terminal (serial) interface for  changing parameters such as baud rate, character size, and so on. The  first thing you need to do is include the file &lt;tt&gt;'termios.h&gt;&lt;span style="font-family: Georgia,serif;"&gt;'&lt;/span&gt;&lt;/tt&gt;;  this defines the terminal control structure as well as the POSIX  control functions. &lt;/p&gt;&lt;p&gt;The two most important POSIX functions are &lt;i&gt;tcgetattr(3)&lt;/i&gt; and &lt;i&gt; tcsetattr(3)&lt;/i&gt;. These get and set terminal attributes, respectively;  you provide a pointer to a &lt;i&gt;termios&lt;/i&gt; structure that contains all  of the serial options available:  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 3 - Termios  Structure Members&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Member&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_cflag&lt;/td&gt;&lt;td&gt;Control options&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_lflag&lt;/td&gt;&lt;td&gt;Line options&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_iflag&lt;/td&gt;&lt;td&gt;Input options&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_oflag&lt;/td&gt;&lt;td&gt;Output options&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_cc&lt;/td&gt;&lt;td&gt;Control characters&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_ispeed&lt;/td&gt;&lt;td&gt;Input baud (new interface)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;c_ospeed&lt;/td&gt;&lt;td&gt;Output baud (new interface)&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h3&gt;&lt;a name="3_1_1"&gt;Control Options&lt;/a&gt;&lt;/h3&gt;  The &lt;i&gt;c_cflag&lt;/i&gt; member controls the baud rate, number of data bits,  parity, stop bits, and hardware flow control. There are constants for  all of the supported configurations.  &lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 4 -  Constants for the c_cflag Member&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CBAUD&lt;/td&gt;&lt;td&gt;Bit mask for baud rate&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B0&lt;/td&gt;&lt;td&gt;0 baud (drop DTR)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B50&lt;/td&gt;&lt;td&gt;50 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B75&lt;/td&gt;&lt;td&gt;75 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B110&lt;/td&gt;&lt;td&gt;110 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B134&lt;/td&gt;&lt;td&gt;134.5 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B150&lt;/td&gt;&lt;td&gt;150 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B200&lt;/td&gt;&lt;td&gt;200 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B300&lt;/td&gt;&lt;td&gt;300 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B600&lt;/td&gt;&lt;td&gt;600 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B1200&lt;/td&gt;&lt;td&gt;1200 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B1800&lt;/td&gt;&lt;td&gt;1800 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B2400&lt;/td&gt;&lt;td&gt;2400 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B4800&lt;/td&gt;&lt;td&gt;4800 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B9600&lt;/td&gt;&lt;td&gt;9600 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B19200&lt;/td&gt;&lt;td&gt;19200 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B38400&lt;/td&gt;&lt;td&gt;38400 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B57600&lt;/td&gt;&lt;td&gt;57,600 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B76800&lt;/td&gt;&lt;td&gt;76,800 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;B115200&lt;/td&gt;&lt;td&gt;115,200 baud&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;EXTA&lt;/td&gt;&lt;td&gt;External rate clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;EXTB&lt;/td&gt;&lt;td&gt;External rate clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CSIZE&lt;/td&gt;&lt;td&gt;Bit mask for data bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CS5&lt;/td&gt;&lt;td&gt;5 data bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CS6&lt;/td&gt;&lt;td&gt;6 data bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CS7&lt;/td&gt;&lt;td&gt;7 data bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CS8&lt;/td&gt;&lt;td&gt;8 data bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CSTOPB&lt;/td&gt;&lt;td&gt;2 stop bits (1 otherwise)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CREAD&lt;/td&gt;&lt;td&gt;Enable receiver&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;PARENB&lt;/td&gt;&lt;td&gt;Enable parity bit&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;PARODD&lt;/td&gt;&lt;td&gt;Use odd parity instead of even&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;HUPCL&lt;/td&gt;&lt;td&gt;Hangup (drop DTR) on last close&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CLOCAL&lt;/td&gt;&lt;td&gt;Local line - do not change "owner" of port&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;LOBLK&lt;/td&gt;&lt;td&gt;Block job control output&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CNEW_RTSCTS &lt;br /&gt;CRTSCTS&lt;/td&gt;&lt;td&gt;Enable hardware flow control (not supported  on all  platforms)&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;p&gt;The &lt;i&gt;c_cflag&lt;/i&gt; member contains two options that should always be  enabled, &lt;i&gt;CLOCAL&lt;/i&gt; and &lt;i&gt;CREAD&lt;/i&gt;. These will ensure that your  program does not become the 'owner' of the port subject to sporatic job  control and hangup signals, and also that the serial interface driver  will read incoming data bytes. &lt;/p&gt;&lt;p&gt;The baud rate constants (&lt;i&gt;CBAUD&lt;/i&gt;, &lt;i&gt;B9600&lt;/i&gt;, etc.) are used  for older interfaces that lack the &lt;i&gt;c_ispeed&lt;/i&gt; and &lt;i&gt;c_ospeed&lt;/i&gt;  members. See the next section for information on the POSIX functions  used to set the baud rate. &lt;/p&gt;&lt;p&gt;&lt;b&gt;Never&lt;/b&gt; initialize the &lt;i&gt;c_cflag&lt;/i&gt; (or any other flag)  member directly; you should always use the bitwise AND, OR, and NOT  operators to set or clear bits in the members.  Different operating  system versions (and even patches) can and do use the bits differently,  so using the bitwise operators will prevent you from clobbering a bit  flag that is needed in a newer serial driver. &lt;/p&gt;&lt;h4&gt;Setting the Baud Rate&lt;/h4&gt;&lt;p&gt;The baud rate is stored in different places depending on the  operating system. Older interfaces store the baud rate in the &lt;i&gt;c_cflag&lt;/i&gt;  member using one of the baud rate constants in table 4, while newer  implementations provide the &lt;i&gt;c_ispeed&lt;/i&gt; and &lt;i&gt;c_ospeed&lt;/i&gt; members  that contain the actual baud rate value. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;cfsetospeed(3)&lt;/i&gt; and &lt;i&gt;cfsetispeed(3)&lt;/i&gt; functions are  provided to set the baud rate in the &lt;i&gt;termios&lt;/i&gt; structure  regardless of the underlying operating system interface. Typically  you'd use the following code to set the baud rate: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 2 - Setting the baud rate. &lt;/p&gt;&lt;pre&gt;struct termios options;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Get the current options for the port...&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;tcgetattr(fd, &amp;amp;options);&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Set the baud rates to 19200...&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;cfsetispeed(&amp;amp;options, B19200);&lt;br /&gt;cfsetospeed(&amp;amp;options, B19200);&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Enable the receiver and set local mode...&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;options.c_cflag |= (CLOCAL | CREAD);&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* Set the new options for the port...&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;tcsetattr(fd, TCSANOW, &amp;amp;options);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;tcgetattr(3)&lt;/i&gt; function fills the termios structure you  provide with the current serial port configuration. After we set the  baud rates and enable local mode and serial data receipt, we select the  new configuration using &lt;i&gt;tcsetattr(3)&lt;/i&gt;. The &lt;i&gt;TCSANOW&lt;/i&gt;  constant specifies that all changes should occur immediately without  waiting for output data to finish sending or input data to finish  receiving. There are other constants to wait for input and output to  finish or to flush the input and output buffers. &lt;/p&gt;&lt;p&gt;Most systems do not support different input and output speeds, so be  sure to set both to the same value for maximum portability.  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 5 -  Constants for tcsetattr&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSANOW&lt;/td&gt;&lt;td&gt;Make changes now without waiting for data to  complete&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSADRAIN&lt;/td&gt;&lt;td&gt;Wait until everything has been transmitted&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSAFLUSH&lt;/td&gt;&lt;td&gt;Flush input and output buffers and make the  change&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h4&gt;Setting the Character Size&lt;/h4&gt;&lt;p&gt;Unlike the baud rate, there is no convienience function to set the  character size. Instead you must do a little bitmasking to set things  up. The character size is specified in bits: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_cflag &amp;amp;= ~CSIZE; /* Mask the character size bits */&lt;br /&gt;options.c_cflag |= CS8;    /* Select 8 data bits */&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h4&gt;Setting Parity Checking&lt;/h4&gt;&lt;p&gt;Like the character size you must manually set the parity enable and  parity type bits. UNIX serial drivers support even, odd, and no parity  bit generation. Space parity can be simulated with clever coding. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;No parity (8N1):&lt;/li&gt;&lt;pre&gt;options.c_cflag &amp;amp;= ~PARENB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |= CS8;&lt;br /&gt;&lt;/pre&gt;&lt;li&gt;Even parity (7E1):&lt;/li&gt;&lt;pre&gt;options.c_cflag |= PARENB&lt;br /&gt;options.c_cflag &amp;amp;= ~PARODD&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |= CS7;&lt;br /&gt;&lt;/pre&gt;&lt;li&gt;Odd parity (7O1):&lt;/li&gt;&lt;pre&gt;options.c_cflag |= PARENB&lt;br /&gt;options.c_cflag |= PARODD&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |= CS7;&lt;br /&gt;&lt;/pre&gt;&lt;li&gt;Space parity is setup the same as no parity (7S1):&lt;/li&gt;&lt;pre&gt;options.c_cflag &amp;amp;= ~PARENB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |= CS8;&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h4&gt;Setting Hardware Flow Control&lt;/h4&gt;&lt;p&gt;Some versions of UNIX support hardware flow control using the CTS  (Clear To Send) and RTS (Request To Send) signal lines. If the &lt;i&gt; CNEW_RTSCTS&lt;/i&gt; or &lt;i&gt;CRTSCTS&lt;/i&gt; constants are defined on your system  then hardware flow control is probably supported. Do the following to  enable hardware flow control: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_cflag |= CNEW_RTSCTS;    /* Also called CRTSCTS */&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;Similarly, to disable hardware flow control: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_cflag &amp;amp;= ~CNEW_RTSCTS;&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h3&gt;&lt;a name="3_1_2"&gt;Local Options&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The local modes member &lt;i&gt;c_lflag&lt;/i&gt; controls how input characters  are managed by the serial driver. In general you will configure the &lt;i&gt; c_lflag&lt;/i&gt; member for &lt;i&gt;canonical&lt;/i&gt; or &lt;i&gt;raw&lt;/i&gt; input.  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 6 -  Constants for the c_lflag Member&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ISIG&lt;/td&gt;&lt;td&gt;Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT  signals&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ICANON&lt;/td&gt;&lt;td&gt;Enable canonical input (else raw)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;XCASE&lt;/td&gt;&lt;td&gt;Map uppercase \lowercase (obsolete)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHO&lt;/td&gt;&lt;td&gt;Enable echoing of input characters&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHOE&lt;/td&gt;&lt;td&gt;Echo erase character as BS-SP-BS&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHOK&lt;/td&gt;&lt;td&gt;Echo NL after kill character&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHONL&lt;/td&gt;&lt;td&gt;Echo NL&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NOFLSH&lt;/td&gt;&lt;td&gt;Disable flushing of input buffers after  interrupt or quit characters&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IEXTEN&lt;/td&gt;&lt;td&gt;Enable extended functions&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHOCTL&lt;/td&gt;&lt;td&gt;Echo control characters as ^char and delete as  ~?&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHOPRT&lt;/td&gt;&lt;td&gt;Echo erased character as character erased&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ECHOKE&lt;/td&gt;&lt;td&gt;BS-SP-BS entire line on line kill&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FLUSHO&lt;/td&gt;&lt;td&gt;Output being flushed&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;PENDIN&lt;/td&gt;&lt;td&gt;Retype pending input at next read or input char&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TOSTOP&lt;/td&gt;&lt;td&gt;Send SIGTTOU for background output&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h4&gt;Choosing Canonical Input&lt;/h4&gt;&lt;p&gt;Canonical input is line-oriented. Input characters are put into a  buffer which can be edited interactively by the user until a CR  (carriage return) or LF (line feed) character is received. &lt;/p&gt;&lt;p&gt;When selecting this mode you normally select the &lt;i&gt;ICANON&lt;/i&gt;, &lt;i&gt; ECHO&lt;/i&gt;, and &lt;i&gt;ECHOE&lt;/i&gt; options: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_lflag |= (ICANON | ECHO | ECHOE);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h4&gt;Choosing Raw Input&lt;/h4&gt;&lt;p&gt;Raw input is unprocessed. Input characters are passed through  exactly as they are received, when they are received. Generally you'll  deselect the &lt;i&gt;ICANON&lt;/i&gt;, &lt;i&gt;ECHO&lt;/i&gt;, &lt;i&gt;ECHOE&lt;/i&gt;, and &lt;i&gt;ISIG&lt;/i&gt;  options when using raw input: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_lflag &amp;amp;= ~(ICANON | ECHO | ECHOE | ISIG);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h4&gt;A Note About Input Echo&lt;/h4&gt;&lt;p&gt;&lt;b&gt;Never&lt;/b&gt; enable input echo (&lt;i&gt;ECHO, ECHOE&lt;/i&gt;) when sending  commands to a MODEM or other computer that is echoing characters, as  you will generate a feedback loop between the two serial interfaces! &lt;/p&gt;&lt;h3&gt;&lt;a name="3_1_3"&gt;Input Options&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The input modes member &lt;i&gt;c_iflag&lt;/i&gt; controls any input processing  that is done to characters received on the port. Like the &lt;i&gt;c_cflag&lt;/i&gt;  field, the final value stored in &lt;i&gt;c_iflag&lt;/i&gt; is the bitwise OR of  the desired options.  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 7 -  Constants for the c_iflag Member&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;INPCK&lt;/td&gt;&lt;td&gt;Enable parity check&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IGNPAR&lt;/td&gt;&lt;td&gt;Ignore parity errors&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;PARMRK&lt;/td&gt;&lt;td&gt;Mark parity errors&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ISTRIP&lt;/td&gt;&lt;td&gt;Strip parity bits&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IXON&lt;/td&gt;&lt;td&gt;Enable software flow control (outgoing)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IXOFF&lt;/td&gt;&lt;td&gt;Enable software flow control (incoming)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IXANY&lt;/td&gt;&lt;td&gt;Allow any character to start flow again&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IGNBRK&lt;/td&gt;&lt;td&gt;Ignore break condition&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BRKINT&lt;/td&gt;&lt;td&gt;Send a SIGINT when a break condition is detected&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;INLCR&lt;/td&gt;&lt;td&gt;Map NL to CR&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IGNCR&lt;/td&gt;&lt;td&gt;Ignore CR&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ICRNL&lt;/td&gt;&lt;td&gt;Map CR to NL&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IUCLC&lt;/td&gt;&lt;td&gt;Map uppercase to lowercase&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;IMAXBEL&lt;/td&gt;&lt;td&gt;Echo BEL on input line too long&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h4&gt;Setting Input Parity Options&lt;/h4&gt;&lt;p&gt;You should enable input parity checking when you have enabled parity  in the &lt;i&gt;c_cflag&lt;/i&gt; member (&lt;i&gt;PARENB&lt;/i&gt;). The revelant constants  for input parity checking are &lt;i&gt;INPCK&lt;/i&gt;, &lt;i&gt;IGNPAR&lt;/i&gt;, &lt;i&gt;PARMRK&lt;/i&gt; , and &lt;i&gt;ISTRIP&lt;/i&gt;. Generally you will select &lt;i&gt;INPCK&lt;/i&gt; and &lt;i&gt; ISTRIP &lt;/i&gt;to enable checking and stripping of the parity bit: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_iflag |= (INPCK | ISTRIP);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;&lt;i&gt;IGNPAR&lt;/i&gt; is a somewhat dangerous option that tells the serial  driver to ignore parity errors and pass the incoming data through as if  no errors had occurred. This can be useful for testing the quality of a  communications link, but in general is not used for practical reasons. &lt;/p&gt;&lt;p&gt;&lt;i&gt;PARMRK&lt;/i&gt; causes parity errors to be 'marked' in the input  stream using special characters. If &lt;i&gt;IGNPAR&lt;/i&gt; is enabled, a NUL  character (000 octal) is sent to your program before every character  with a parity error. Otherwise, a DEL (177 octal) and NUL character is  sent along with the bad character. &lt;/p&gt;&lt;h4&gt;Setting Software Flow Control&lt;/h4&gt;&lt;p&gt;Software flow control is enabled using the &lt;i&gt;IXON&lt;/i&gt;, &lt;i&gt;IXOFF&lt;/i&gt; , and &lt;i&gt;IXANY&lt;/i&gt; constants: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_iflag |= (IXON | IXOFF | IXANY);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;To disable software flow control simply mask those bits: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_iflag &amp;amp;= ~(IXON | IXOFF | IXANY);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The XON (start data) and XOFF (stop data) characters are defined in  the &lt;i&gt;c_cc&lt;/i&gt; array described below. &lt;/p&gt;&lt;h3&gt;&lt;a name="3_1_4"&gt;Output Options&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;i&gt;c_oflag&lt;/i&gt; member contains output filtering options. Like  the input modes, you can select processed or raw data output.  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="50%"&gt;&lt;caption align="CENTER"&gt;Table 8 -  Constants for the c_oflag Member&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;OPOST&lt;/td&gt;&lt;td&gt;Postprocess output (not set = raw output)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;OLCUC&lt;/td&gt;&lt;td&gt;Map lowercase to uppercase&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ONLCR&lt;/td&gt;&lt;td&gt;Map NL to CR-NL&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;OCRNL&lt;/td&gt;&lt;td&gt;Map CR to NL&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NOCR&lt;/td&gt;&lt;td&gt;No CR output at column 0&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ONLRET&lt;/td&gt;&lt;td&gt;NL performs CR function&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;OFILL&lt;/td&gt;&lt;td&gt;Use fill characters for delay&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;OFDEL&lt;/td&gt;&lt;td&gt;Fill character is DEL&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NLDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed between lines&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NL0&lt;/td&gt;&lt;td&gt;No delay for NLs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NL1&lt;/td&gt;&lt;td&gt;Delay further output after newline for 100  milliseconds&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CRDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed to return carriage to  left column&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CR0&lt;/td&gt;&lt;td&gt;No delay for CRs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CR1&lt;/td&gt;&lt;td&gt;Delay after CRs depending on current column position&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CR2&lt;/td&gt;&lt;td&gt;Delay 100 milliseconds after sending CRs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CR3&lt;/td&gt;&lt;td&gt;Delay 150 milliseconds after sending CRs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TABDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed after TABs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TAB0&lt;/td&gt;&lt;td&gt;No delay for TABs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TAB1&lt;/td&gt;&lt;td&gt;Delay after TABs depending on current column  position&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TAB2&lt;/td&gt;&lt;td&gt;Delay 100 milliseconds after sending TABs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TAB3&lt;/td&gt;&lt;td&gt;Expand TAB characters to spaces&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BSDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed after BSs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BS0&lt;/td&gt;&lt;td&gt;No delay for BSs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BS1&lt;/td&gt;&lt;td&gt;Delay 50 milliseconds after sending BSs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VTDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed after VTs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VT0&lt;/td&gt;&lt;td&gt;No delay for VTs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VT1&lt;/td&gt;&lt;td&gt;Delay 2 seconds after sending VTs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FFDLY&lt;/td&gt;&lt;td&gt;Mask for delay time needed after FFs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FF0&lt;/td&gt;&lt;td&gt;No delay for FFs&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FF1&lt;/td&gt;&lt;td&gt;Delay 2 seconds after sending FFs&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h4&gt;Choosing Processed Output&lt;/h4&gt;&lt;p&gt;Processed output is selected by setting the &lt;i&gt;OPOST&lt;/i&gt; option in  the &lt;i&gt;c_oflag&lt;/i&gt; member: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_oflag |= OPOST;&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;Of all the different options, you will only probably use the &lt;i&gt;ONLCR&lt;/i&gt;  option which maps newlines into CR-LF pairs. The rest of the output  options are primarily historic and date back to the time when line  printers and terminals could not keep up with the serial data stream! &lt;/p&gt;&lt;h4&gt;Choosing Raw Output&lt;/h4&gt;&lt;p&gt;Raw output is selected by resetting the &lt;i&gt;OPOST&lt;/i&gt; option in the &lt;i&gt; c_oflag&lt;/i&gt; member: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;options.c_oflag &amp;amp;= ~OPOST;&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;When the &lt;i&gt;OPOST&lt;/i&gt; option is disabled, all other option bits in &lt;i&gt; c_oflag&lt;/i&gt; are ignored. &lt;/p&gt;&lt;h3&gt;&lt;a name="3_1_5"&gt;Control Characters&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;i&gt;c_cc&lt;/i&gt; character array contains control character  definitions as well as timeout parameters. Constants are defined for  every element of this array.  &lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 9 - Control Characters in  the c_cc Member&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Key&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VINTR&lt;/td&gt;&lt;td&gt;Interrupt&lt;/td&gt;&lt;td&gt;CTRL-C&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VQUIT&lt;/td&gt;&lt;td&gt;Quit&lt;/td&gt;&lt;td&gt;CTRL-Z&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VERASE&lt;/td&gt;&lt;td&gt;Erase&lt;/td&gt;&lt;td&gt;Backspace (BS)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VKILL&lt;/td&gt;&lt;td&gt;Kill-line&lt;/td&gt;&lt;td&gt;CTRL-U&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VEOF&lt;/td&gt;&lt;td&gt;End-of-file&lt;/td&gt;&lt;td&gt;CTRL-D&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VEOL&lt;/td&gt;&lt;td&gt;End-of-line&lt;/td&gt;&lt;td&gt;Carriage return (CR)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VEOL2&lt;/td&gt;&lt;td&gt;Second end-of-line&lt;/td&gt;&lt;td&gt;Line feed (LF)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VMIN&lt;/td&gt;&lt;td&gt;Minimum number of characters to read&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VTIME&lt;/td&gt;&lt;td&gt;Time to wait for data (tenths of seconds)&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h4&gt;Setting Software Flow Control Characters&lt;/h4&gt;&lt;p&gt;The &lt;i&gt;VSTART&lt;/i&gt; and &lt;i&gt;VSTOP&lt;/i&gt; elements of the &lt;i&gt;c_cc&lt;/i&gt; array  contain the characters used for software flow control. Normally they  should be set to DC1 (021 octal) and DC3 (023 octal) which represent  the ASCII standard XON and XOFF characters. &lt;/p&gt;&lt;h4&gt;Setting Read Timeouts&lt;/h4&gt;&lt;p&gt;UNIX serial interface drivers provide the ability to specify  character and packet timeouts. Two elements of the &lt;i&gt;c_cc&lt;/i&gt; array  are used for timeouts: &lt;i&gt;VMIN&lt;/i&gt; and &lt;i&gt;VTIME&lt;/i&gt;. &lt;b&gt;Timeouts are  ignored in canonical input mode or when the &lt;i&gt;NDELAY&lt;/i&gt; option is set  on the file via &lt;i&gt;open&lt;/i&gt; or &lt;i&gt;fcntl&lt;/i&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;VMIN&lt;/i&gt; specifies the minimum number of characters to read. If  it is set to 0, then the &lt;i&gt;VTIME&lt;/i&gt; value specifies the time to wait  for every character read. Note that this does not mean that a &lt;i&gt;read&lt;/i&gt;  call for N bytes will wait for N characters to come in. Rather, the  timeout will apply to the first character and the &lt;i&gt;read&lt;/i&gt; call will  return the number of characters immediately available (up to the number  you request). &lt;/p&gt;&lt;p&gt;If &lt;i&gt;VMIN&lt;/i&gt; is non-zero, &lt;i&gt;VTIME&lt;/i&gt; specifies the time to wait  for the first character read. If a character is read within the time  given, any read will block (wait) until all &lt;i&gt;VMIN&lt;/i&gt; characters are  read. That is, once the first character is read, the serial interface  driver expects to receive an entire packet of characters (&lt;i&gt;VMIN&lt;/i&gt;  bytes total). If no character is read within the time allowed, then  the call to &lt;i&gt;read&lt;/i&gt; returns 0. This method allows you to tell the  serial driver you need exactly N bytes and any &lt;i&gt;read&lt;/i&gt; call will  return 0 or N bytes. However, the timeout only applies to the first  character read, so if for some reason the driver misses one character  inside the N byte packet then the &lt;i&gt;read&lt;/i&gt; call could block forever  waiting for additional input characters. &lt;/p&gt;&lt;p&gt;&lt;i&gt;VTIME&lt;/i&gt; specifies the amount of time to wait for incoming  characters in tenths of seconds. If &lt;i&gt;VTIME&lt;/i&gt; is set to 0 (the  default), reads will block (wait) indefinitely unless the &lt;i&gt;NDELAY&lt;/i&gt;  option is set on the port with &lt;i&gt;open&lt;/i&gt; or &lt;i&gt;fcntl&lt;/i&gt;. &lt;/p&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="modem"&gt;Chapter 3, MODEM Communications&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This chapter covers the basics of dialup telephone  Modulator/Demodulator (MODEM) communications. Examples are provided for  MODEMs that use the defacto standard "AT" command set. &lt;/p&gt;&lt;h2&gt;&lt;a name="4_1"&gt;What Is a MODEM?&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;MODEMs are devices that modulate serial data into frequencies that  can be transferred over an analog data link such as a telephone line or  cable TV connection. A standard telephone MODEM converts serial data  into tones that can be passed over the phone lines; because of the  speed and complexity of the conversion these tones sound more like loud  screeching if you listen to them. &lt;/p&gt;&lt;p&gt;Telephone MODEMs are available today that can transfer data across a  telephone line at nearly 53,000 bits per second, or 53kbps. In  addition, most MODEMs use data compression technology that can increase  the bit rate to well over 100kbps on some types of data. &lt;/p&gt;&lt;h2&gt;&lt;a name="4_2"&gt;Communicating With a MODEM&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The first step in communicating with a MODEM is to open and  configure the port for &lt;i&gt;raw&lt;/i&gt; input: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 3 - Configuring the port for raw input. &lt;/p&gt;&lt;pre&gt;int            fd;&lt;br /&gt;struct termios options;&lt;br /&gt;&lt;br /&gt;/* open the port */&lt;br /&gt;fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt;fcntl(fd, F_SETFL, 0);&lt;br /&gt;&lt;br /&gt;/* get the current options */&lt;br /&gt;tcgetattr(fd, &amp;amp;options);&lt;br /&gt;&lt;br /&gt;/* set raw input, 1 second timeout */&lt;br /&gt;options.c_cflag     |= (CLOCAL | CREAD);&lt;br /&gt;options.c_lflag     &amp;amp;= ~(ICANON | ECHO | ECHOE | ISIG);&lt;br /&gt;options.c_oflag     &amp;amp;= ~OPOST;&lt;br /&gt;options.c_cc[VMIN]  = 0;&lt;br /&gt;options.c_cc[VTIME] = 10;&lt;br /&gt;&lt;br /&gt;/* set the options */&lt;br /&gt;tcsetattr(fd, TCSANOW, &amp;amp;options);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;Next you need to establish communications with the MODEM. The best  way to do this is by sending the "AT" command to the MODEM. This also  allows smart MODEMs to detect the baud you are using. When the MODEM is  connected correctly and powered on it will respond with the response  "OK". &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 4 - Initializing the MODEM. &lt;/p&gt;&lt;pre&gt;int                  /* O - 0 = MODEM ok, -1 = MODEM bad */&lt;br /&gt;init_modem(int fd)   /* I - Serial port file */&lt;br /&gt;{&lt;br /&gt; char buffer[255];  /* Input buffer */&lt;br /&gt; char *bufptr;      /* Current char in buffer */&lt;br /&gt; int  nbytes;       /* Number of bytes read */&lt;br /&gt; int  tries;        /* Number of tries so far */&lt;br /&gt;&lt;br /&gt; for (tries = 0; tries &lt; 3; tries ++)&lt;br /&gt; {&lt;br /&gt;  /* send an AT command followed by a CR */&lt;br /&gt;   if (write(fd, "AT\r", 3) &lt; 3)&lt;br /&gt;     continue;&lt;br /&gt;&lt;br /&gt;  /* read characters into our string buffer until we get a CR or NL */&lt;br /&gt;   bufptr = buffer;&lt;br /&gt;   while ((nbytes = read(fd, bufptr, buffer + sizeof(buffer) - bufptr - 1)) &gt; 0)&lt;br /&gt;   {&lt;br /&gt;     bufptr += nbytes;&lt;br /&gt;     if (bufptr[-1] == '\n' || bufptr[-1] == '\r')&lt;br /&gt;       break;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;  /* nul terminate the string and see if we got an OK response */&lt;br /&gt;   *bufptr = '\0';&lt;br /&gt;&lt;br /&gt;   if (strncmp(buffer, "OK", 2) == 0)&lt;br /&gt;     return (0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return (-1);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h3&gt;&lt;a name="4_2_1"&gt;Standard MODEM Commands&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Most MODEMs support the "AT" command set, so called because each  command starts with the "AT" characters. Each command is sent with the  "AT" characters starting in the first column followed by the specific  command and a carriage return (CR, 015 octal). After processing the  command the MODEM will reply with one of several textual messages  depending on the command. &lt;/p&gt;&lt;h4&gt;ATD - Dial A Number&lt;/h4&gt;&lt;p&gt;The &lt;i&gt;ATD&lt;/i&gt; command dials the specified number. In addition to  numbers and dashes you can specify tone ("T") or pulse ("P") dialing,  pause for one second (","), and wait for a dialtone ("W"): &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;ATDT 555-1212&lt;br /&gt;ATDT 18008008008W1234,1,1234&lt;br /&gt;ATD T555-1212WP1234&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The MODEM will reply with one of the following messages: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;NO DIALTONE&lt;br /&gt;BUSY&lt;br /&gt;NO CARRIER&lt;br /&gt;CONNECT&lt;br /&gt;CONNECT &lt;i&gt;baud&lt;/i&gt; &lt;/pre&gt;&lt;/ul&gt;&lt;h4&gt;ATH - Hang Up&lt;/h4&gt;&lt;p&gt;The &lt;i&gt;ATH&lt;/i&gt; command causes the MODEM to hang up. Since the MODEM  must be in "command" mode you probably won't use it during a normal  phone call. &lt;/p&gt;&lt;p&gt;Most MODEMs will also hang up if DTR is dropped; you can do this by  setting the baud to 0 for at least 1 second. Dropping DTR also returns  the MODEM to command mode. &lt;/p&gt;&lt;p&gt;After a successful hang up the MODEM will reply with "NO CARRIER".  If the MODEM is still connected the "CONNECT" or "CONNECT baud" message  will be sent. &lt;/p&gt;&lt;h4&gt;ATZ - Reset MODEM&lt;/h4&gt;  The &lt;i&gt;ATZ&lt;/i&gt; command resets the MODEM. The MODEM will reply with the  string "OK".  &lt;h3&gt;&lt;a name="4_2_2"&gt;Common MODEM Communication Problems&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;First and foremost, &lt;i&gt;don't forget to disable input echoing&lt;/i&gt;.  Input echoing will cause a feedback loop between the MODEM and  computer. &lt;/p&gt;&lt;p&gt;Second, when sending MODEM commands you must terminate them with a  carriage return (CR) and not a newline (NL). The C character constant  for CR is "\r". &lt;/p&gt;&lt;p&gt;Finally, when dealing with a MODEM make sure you use a baud that the  MODEM supports. While many MODEMs do auto-baud detection, some have  limits (19.2kbps is common) that you must observe. &lt;/p&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="advanced"&gt;Chapter 4, Advanced Serial  Programming&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This chapter covers advanced serial programming techniques using the &lt;i&gt; ioctl(2)&lt;/i&gt; and &lt;i&gt;select(2)&lt;/i&gt; system calls. &lt;/p&gt;&lt;h2&gt;&lt;a name="5_1"&gt;Serial Port IOCTLs&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;In Chapter 2, Configuring the Serial Port we  used the &lt;i&gt;tcgetattr&lt;/i&gt; and &lt;i&gt;tcsetattr&lt;/i&gt; functions to configure  the serial port. Under UNIX these functions use the &lt;i&gt;ioctl(2)&lt;/i&gt;  system call to do their magic. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;ioctl&lt;/i&gt; system call takes three arguments: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;int ioctl(int fd, int request, ...);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;fd&lt;/i&gt; argument specifies the serial port file descriptor.  The &lt;i&gt;request&lt;/i&gt; argument is a constant defined in the &lt;code&gt; &lt;termios.h&gt;&lt;/code&gt; header file and is typically one of the following:  &lt;/p&gt;&lt;center&gt; &lt;table border="1" width="80%"&gt;&lt;caption align="CENTER"&gt;Table 10 - IOCTL  Requests for Serial Ports&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Request&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th nowrap="nowrap"&gt;POSIX Function&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCGETS&lt;/td&gt;&lt;td&gt;Gets the current serial port settings.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; tcgetattr&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSETS&lt;/td&gt;&lt;td&gt;Sets the serial port settings immediately.&lt;/td&gt;&lt;td nowrap="nowrap"&gt;tcsetattr(fd, TCSANOW, &amp;amp;options)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSETSF&lt;/td&gt;&lt;td&gt;Sets the serial port settings after flushing  the input and output buffers.&lt;/td&gt;&lt;td nowrap="nowrap"&gt;tcsetattr(fd, TCSANOW,  &amp;amp;options)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSETSW&lt;/td&gt;&lt;td&gt;Sets the serial port settings after allowing  the input and output buffers  to drain/empty.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; tcsetattr(fd, TCSANOW, &amp;amp;options)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCSBRK&lt;/td&gt;&lt;td&gt;Sends a break for the given time.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; tcsendbreak, tcdrain&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCXONC&lt;/td&gt;&lt;td&gt;Controls software flow control.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; tcflow&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TCFLSH&lt;/td&gt;&lt;td&gt;Flushes the input and/or output queue.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; tcflush&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCMGET&lt;/td&gt;&lt;td&gt;Returns the state of the "MODEM" bits.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; None&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCMSET&lt;/td&gt;&lt;td&gt;Sets the state of the "MODEM" bits.&lt;/td&gt;&lt;td nowrap="nowrap"&gt; None&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FIONREAD&lt;/td&gt;&lt;td&gt;Returns the number of bytes in the input  buffer.&lt;/td&gt;&lt;td nowrap="nowrap"&gt;None&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h3&gt;&lt;a name="5_1_1"&gt;Getting the Control Signals&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;TIOCMGET&lt;/code&gt;&lt;i&gt; ioctl&lt;/i&gt; gets the current "MODEM"  status bits, which consist of all of the RS-232 signal lines except &lt;b&gt; RXD&lt;/b&gt; and &lt;b&gt;TXD&lt;/b&gt;:  &lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 11 - Control Signal  Constants&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Constant&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_LE&lt;/td&gt;&lt;td&gt;DSR (data set ready/line enable)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_DTR&lt;/td&gt;&lt;td&gt;DTR (data terminal ready)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_RTS&lt;/td&gt;&lt;td&gt;RTS (request to send)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_ST&lt;/td&gt;&lt;td&gt;Secondary TXD (transmit)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_SR&lt;/td&gt;&lt;td&gt;Secondary RXD (receive)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_CTS&lt;/td&gt;&lt;td&gt;CTS (clear to send)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_CAR&lt;/td&gt;&lt;td&gt;DCD (data carrier detect)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_CD&lt;/td&gt;&lt;td&gt;Synonym for TIOCM_CAR&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_RNG&lt;/td&gt;&lt;td&gt;RNG (ring)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_RI&lt;/td&gt;&lt;td&gt;Synonym for TIOCM_RNG&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;TIOCM_DSR&lt;/td&gt;&lt;td&gt;DSR (data set ready)&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;p&gt;To get the status bits, call &lt;i&gt;ioctl&lt;/i&gt; with a pointer to an  integer to hold the bits: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 5 - Getting the MODEM status bits. &lt;/p&gt;&lt;pre&gt;#include &lt;unistd.h&gt;&lt;br /&gt;#include &lt;termios.h&gt;&lt;br /&gt;&lt;br /&gt;int fd;&lt;br /&gt;int status;&lt;br /&gt;&lt;br /&gt;ioctl(fd, TIOCMGET, &amp;amp;status);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;h3&gt;&lt;a name="5_1_2"&gt;Setting the Control Signals&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;TIOCMSET&lt;/code&gt;&lt;i&gt; ioctl&lt;/i&gt; sets the "MODEM" status bits  defined above. To drop the DTR signal you can do: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 6 - Dropping DTR with the TIOCMSET ioctl. &lt;/p&gt;&lt;pre&gt;#include 'unistd.h'&lt;br /&gt;#include 'termios.h'&lt;br /&gt;&lt;br /&gt;int fd;&lt;br /&gt;int status;&lt;br /&gt;&lt;br /&gt;ioctl(fd, TIOCMGET, &amp;amp;status);&lt;br /&gt;&lt;br /&gt;status &amp;amp;= ~TIOCM_DTR;&lt;br /&gt;&lt;br /&gt;ioctl(fd, TIOCMSET, status);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The bits that can be set depend on the operating system, driver, and  modes in use. Consult your operating system documentation for more  information. &lt;/p&gt;&lt;h3&gt;&lt;a name="5_1_3"&gt;Getting the Number of Bytes Available&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;FIONREAD&lt;/code&gt;&lt;i&gt; ioctl&lt;/i&gt; gets the number of bytes in  the serial port input buffer. As with &lt;code&gt;TIOCMGET&lt;/code&gt; you pass in  a pointer to an integer to hold the number of bytes: &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 7 - Getting the number of bytes in the input buffer. &lt;/p&gt;&lt;pre&gt;#include 'unistd.h'&lt;br /&gt;#include 'termios.h'&lt;br /&gt;&lt;br /&gt;int fd;&lt;br /&gt;int bytes;&lt;br /&gt;&lt;br /&gt;ioctl(fd, FIONREAD, &amp;amp;bytes);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;This can be useful when polling a serial port for data, as your  program can determine the number of bytes in the input buffer before  attempting a read. &lt;/p&gt;&lt;h2&gt;&lt;a name="5_2"&gt;Selecting Input from a Serial Port&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;While simple applications can poll or wait on data coming from the  serial port, most applications are not simple and need to handle input  from multiple sources. &lt;/p&gt;&lt;p&gt;UNIX provides this capability through the &lt;i&gt;select(2)&lt;/i&gt; system  call. This system call allows your program to check for input, output,  or error conditions on one or more file descriptors. The file  descriptors can point to serial ports, regular files, other devices,  pipes, or sockets. You can poll to check for pending input, wait for  input indefinitely, or timeout after a specific amount of time, making  the &lt;i&gt;select&lt;/i&gt; system call extremely flexible. &lt;/p&gt;&lt;p&gt;Most GUI Toolkits provide an interface to &lt;i&gt;select&lt;/i&gt;; we will  discuss the X Intrinsics ("Xt") library later in this chapter. &lt;/p&gt;&lt;h3&gt;&lt;a name="5_2_1"&gt;The SELECT System Call&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The &lt;i&gt;select&lt;/i&gt; system call accepts 5 arguments: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;int select(int max_fd, fd_set *input, fd_set *output, fd_set *error,&lt;br /&gt;          struct timeval *timeout);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;max_fd&lt;/i&gt; argument specifies the highest numbered file  descriptor in the &lt;i&gt;input&lt;/i&gt;, &lt;i&gt;output&lt;/i&gt;, and &lt;i&gt;error&lt;/i&gt; sets.  The &lt;i&gt;input&lt;/i&gt;, &lt;i&gt;output&lt;/i&gt;, and &lt;i&gt;error&lt;/i&gt; arguments specify  sets of file descriptors for pending input, output, or error  conditions; specify &lt;code&gt;NULL&lt;/code&gt; to disable monitoring for the  corresponding condition. These sets are initialized using three macros: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;FD_ZERO(fd_set);&lt;br /&gt;FD_SET(fd, fd_set);&lt;br /&gt;FD_CLR(fd, fd_set);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;FD_ZERO&lt;/i&gt; macro clears the set entirely. The &lt;i&gt;FD_SET&lt;/i&gt;  and &lt;i&gt;FD_CLR&lt;/i&gt; macros add and remove a file descriptor from the  set, respectively. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;timeout&lt;/i&gt; argument specifies a timeout value which consists  of seconds (&lt;i&gt;timeout.tv_sec&lt;/i&gt;) and microseconds (&lt;i&gt;timeout.tv_usec&lt;/i&gt; ). To poll one or more file descriptors, set the seconds and  microseconds to zero. To wait indefinitely specify &lt;code&gt;NULL&lt;/code&gt;  for the timeout pointer. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;select&lt;/i&gt; system call returns the number of file descriptors  that have a pending condition, or -1 if there was an error. &lt;/p&gt;&lt;h3&gt;&lt;a name="5_2_2"&gt;Using the SELECT System Call&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Suppose we are reading data from a serial port and a socket. We want  to check for input from either file descriptor, but want to notify the  user if no data is seen within 10 seconds. To do this we'll need to use  the &lt;i&gt;select&lt;/i&gt; system call:  &lt;!-- PAGE BREAK ----&gt; &lt;/p&gt;&lt;ul&gt;&lt;p&gt;Listing 8 - Using SELECT to process input from more than one source. &lt;/p&gt;&lt;pre&gt;#include 'unistd.h'&lt;br /&gt;#include 'sys/types.h'&lt;br /&gt;#include 'sys/time.h'&lt;br /&gt;#include 'sys/select.h'&lt;br /&gt;&lt;br /&gt;int            n;&lt;br /&gt;int            socket;&lt;br /&gt;int            fd;&lt;br /&gt;int            max_fd;&lt;br /&gt;fd_set         input;&lt;br /&gt;struct timeval timeout;&lt;br /&gt;&lt;br /&gt;/* Initialize the input set */&lt;br /&gt;FD_ZERO(input);&lt;br /&gt;FD_SET(fd, input);&lt;br /&gt;FD_SET(socket, input);&lt;br /&gt;&lt;br /&gt;max_fd = (socket &gt; fd ? socket : fd) + 1;&lt;br /&gt;&lt;br /&gt;/* Initialize the timeout structure */&lt;br /&gt;timeout.tv_sec  = 10;&lt;br /&gt;timeout.tv_usec = 0;&lt;br /&gt;&lt;br /&gt;/* Do the select */&lt;br /&gt;n = select(max_fd,  NULL, NULL, ;&lt;br /&gt;&lt;br /&gt;/* See if there was an error */&lt;br /&gt;if (n 0)&lt;br /&gt; perror("select failed");&lt;br /&gt;else if (n == 0)&lt;br /&gt; puts("TIMEOUT");&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; /* We have input */&lt;br /&gt; if (FD_ISSET(fd, input))&lt;br /&gt;   process_fd();&lt;br /&gt; if (FD_ISSET(socket, input))&lt;br /&gt;   process_socket();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;You'll notice that we first check the return value of the &lt;i&gt;select&lt;/i&gt;  system call. Values of 0 and -1 yield the appropriate warning and  error messages. Values greater than 0 mean that we have data pending on  one or more file descriptors. &lt;/p&gt;&lt;p&gt;To determine which file descriptor(s) have pending input, we use the &lt;i&gt; FD_ISSET&lt;/i&gt; macro to test the input set for each file descriptor. If  the file descriptor flag is set then the condition exists (input  pending in this case) and we need to do something. &lt;/p&gt;&lt;h3&gt;&lt;a name="5_2_3"&gt;Using SELECT with the X Intrinsics Library&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The X Intrinsics library provides an interface to the &lt;i&gt;select&lt;/i&gt;  system call via the &lt;i&gt;XtAppAddInput(3x)&lt;/i&gt; and &lt;i&gt; XtAppRemoveInput(3x)&lt;/i&gt; functions: &lt;/p&gt;&lt;ul&gt;&lt;pre&gt;int XtAppAddInput(XtAppContext context, int fd, int mask,&lt;br /&gt;                 XtInputProc proc, XtPointer data);&lt;br /&gt;void XtAppRemoveInput(XtAppContext context, int input);&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;&lt;p&gt;The &lt;i&gt;select&lt;/i&gt; system call is used internally to implement  timeouts, work procedures, and check for input from the X server. These  functions can be used with any Xt-based toolkit including Xaw, Lesstif,  and Motif. &lt;/p&gt;&lt;p&gt;The &lt;i&gt;proc&lt;/i&gt; argument to &lt;i&gt;XtAppAddInput&lt;/i&gt; specifies the  function to call when the selected condition (e.g. input available)  exists on the file descriptor. In the previous example you could  specify the &lt;i&gt;process_fd&lt;/i&gt; or &lt;i&gt;process_socket&lt;/i&gt; functions. &lt;/p&gt;&lt;p&gt;Because Xt limits your access to the &lt;i&gt;select&lt;/i&gt; system call,  you'll need to implement timeouts through another mechanism, probably  via &lt;i&gt;XtAppAddTimeout(3x)&lt;/i&gt;. &lt;/p&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="pinouts"&gt;Appendix A, Pinouts&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This appendix provides pinout information for many of the common  serial ports you will find. &lt;/p&gt;&lt;h2&gt;&lt;a name="6_1"&gt;RS-232 Pinouts&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;RS-232 comes in three flavors (A, B, C) and uses a 25-pin D-Sub  connector: &lt;/p&gt;&lt;p align="center"&gt;Figure 2 - RS-232 Connector&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/db25.gif" height="83" width="353" /&gt;&lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 12 - RS-232 Signals&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Earth Ground&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;Secondary TXD&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt; Transmit Clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;RXD&lt;/b&gt; - Received Data&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt; Secondary RXD&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS&lt;/b&gt; - Request To Send&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt; Receiver Clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS&lt;/b&gt; - Clear To Send&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt; Unassigned&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;b&gt;DSR&lt;/b&gt; - Data Set Ready&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt; Secondary RTS&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt; - Logic Ground&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR&lt;/b&gt;  - Data Terminal Ready&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD&lt;/b&gt; - Data Carrier Detect&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt; Signal Quality Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;Reserved&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;Ring Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Reserved&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;Data Rate Select&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;Transmit Clock&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;Secondary DCD&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;Secondary CTS&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h2&gt;&lt;a name="6_2"&gt;RS-422 Pinouts&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;RS-422 also uses a 25-pin D-Sub connector, but with differential  signals: &lt;/p&gt;&lt;p align="center"&gt;Figure 3 - RS-422 Connector&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/db25.gif" height="83" width="353" /&gt;&lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 13 - RS-422 Signals&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Earth Ground&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;TXD+&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD-&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt; Transmit Clock-&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;RXD-&lt;/b&gt; - Received Data&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;RXD+&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS-&lt;/b&gt; - Request To Send&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt; Receiver Clock-&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS-&lt;/b&gt; - Clear To Send&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt; Unassigned&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;b&gt;DSR&lt;/b&gt; - Data Set Ready&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;RTS+&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt; - Logic Ground&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR-&lt;/b&gt;  - Data Terminal Ready&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD-&lt;/b&gt; - Data Carrier Detect&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt; Signal Quality Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;Reserved&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Reserved&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR+&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;Unassigned&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;Transmit Clock+&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;DCD+&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;Receiver Clock+&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;CTS+&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h2&gt;&lt;a name="6_3"&gt;RS-574 (IBM PC/AT) Pinouts&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The RS-574 interface is used exclusively by PC manufacturers and  uses a 9-pin male D-Sub connector: &lt;/p&gt;&lt;p align="center"&gt;Figure 4 - RS-574 Connector&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/db9.gif" height="82" width="164" /&gt;&lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 14 - RS-574 (IBM PC/AT)  Signals&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD&lt;/b&gt; - Data Carrier Detect&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt; Data Set Ready&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;RXD&lt;/b&gt; - Received Data&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS&lt;/b&gt;  - Request To Send&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS&lt;/b&gt;  - Clear To Send&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR&lt;/b&gt; - Data Terminal Ready&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt; Ring Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt; - Logic Ground&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;h2&gt;&lt;a name="6_4"&gt;SGI Pinouts&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Older SGI equipment uses a 9-pin female D-Sub connector. Unlike  RS-574, the SGI pinouts nearly match those of RS-232: &lt;/p&gt;&lt;p align="center"&gt;Figure 5 - SGI 9-Pin Connector&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/db9.gif" height="82" width="164" /&gt;&lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 15 - SGI 9-Pin DSUB Signals&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Earth Ground&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;b&gt;DSR&lt;/b&gt; - Data Set  Ready&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt;  - Logic Ground&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;RXD&lt;/b&gt; - Received Data&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD&lt;/b&gt;  - Data Carrier Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS&lt;/b&gt; - Request To Send&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR&lt;/b&gt;  - Data Terminal Ready&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS&lt;/b&gt; - Clear To Send&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;p&gt;The SGI Indigo, Indigo2, and Indy workstations use the Apple 8-pin  MiniDIN connector for their serial ports: &lt;/p&gt;&lt;p align="center"&gt;Figure 6 - SGI 8-Pin Connector&lt;br /&gt;&lt;img src="file:///F:/serial_port/serial_files/mdin8.gif" height="112" width="112" /&gt;&lt;/p&gt;&lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 16 - SGI 8-Pin MiniDIN  Signals&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;th&gt;Pin&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;b&gt;DTR&lt;/b&gt; - Data Terminal Ready&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;&lt;b&gt; RXD&lt;/b&gt; - Received Data&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;&lt;b&gt;CTS&lt;/b&gt; - Clear To Send&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;&lt;b&gt;RTS&lt;/b&gt;  - Request To Send&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;&lt;b&gt;TXD&lt;/b&gt; - Transmitted Data&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;&lt;b&gt;DCD&lt;/b&gt;  - Data Carrier Detect&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt; - Logic Ground&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;&lt;b&gt;GND&lt;/b&gt;  - Logic Ground&lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;&lt;hr /&gt;&lt;h1 align="center"&gt;&lt;a name="ascii"&gt;Appendix B, ASCII Control Codes&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This chapter lists the ASCII control codes and their names. &lt;/p&gt;&lt;h2&gt;&lt;a name="7_1"&gt;Control Codes&lt;/a&gt;&lt;/h2&gt;  The following ASCII characters are used for control purposes:  &lt;center&gt; &lt;table border="1"&gt;&lt;caption align="CENTER"&gt;Table 17 - ASCII Control Codes&lt;/caption&gt; &lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Binary&lt;/th&gt;&lt;th&gt;Octal&lt;/th&gt;&lt;th&gt;Decimal&lt;/th&gt;&lt;th&gt; Hexadecimal&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NUL&lt;/td&gt;&lt;td&gt;00000000&lt;/td&gt;&lt;td&gt;000&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;00&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;SOH&lt;/td&gt;&lt;td&gt;00000001&lt;/td&gt;&lt;td&gt;001&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;01&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;STX&lt;/td&gt;&lt;td&gt;00000010&lt;/td&gt;&lt;td&gt;002&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;02&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ETX&lt;/td&gt;&lt;td&gt;00000011&lt;/td&gt;&lt;td&gt;003&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;03&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;EOT&lt;/td&gt;&lt;td&gt;00000100&lt;/td&gt;&lt;td&gt;004&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;04&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ENQ&lt;/td&gt;&lt;td&gt;00000101&lt;/td&gt;&lt;td&gt;005&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;05&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ACK&lt;/td&gt;&lt;td&gt;00000110&lt;/td&gt;&lt;td&gt;006&lt;/td&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;06&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BEL&lt;/td&gt;&lt;td&gt;00000111&lt;/td&gt;&lt;td&gt;007&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;07&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;BS&lt;/td&gt;&lt;td&gt;00001000&lt;/td&gt;&lt;td&gt;010&lt;/td&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;08&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;HT&lt;/td&gt;&lt;td&gt;00001001&lt;/td&gt;&lt;td&gt;011&lt;/td&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;09&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NL&lt;/td&gt;&lt;td&gt;00001010&lt;/td&gt;&lt;td&gt;012&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;0A&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;VT&lt;/td&gt;&lt;td&gt;00001011&lt;/td&gt;&lt;td&gt;013&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;0B&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NP, FF&lt;/td&gt;&lt;td&gt;00001100&lt;/td&gt;&lt;td&gt;014&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;0C&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CR&lt;/td&gt;&lt;td&gt;00001101&lt;/td&gt;&lt;td&gt;015&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;0D&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;SO&lt;/td&gt;&lt;td&gt;00001110&lt;/td&gt;&lt;td&gt;016&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;0E&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;SI&lt;/td&gt;&lt;td&gt;00001111&lt;/td&gt;&lt;td&gt;017&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;0F&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;DLE&lt;/td&gt;&lt;td&gt;00010000&lt;/td&gt;&lt;td&gt;020&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;XON, DC1&lt;/td&gt;&lt;td&gt;00010001&lt;/td&gt;&lt;td&gt;021&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;11&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;DC2&lt;/td&gt;&lt;td&gt;00010010&lt;/td&gt;&lt;td&gt;022&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;12&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;XOFF, DC3&lt;/td&gt;&lt;td&gt;00010011&lt;/td&gt;&lt;td&gt;023&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;13&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;&lt;td&gt;DC4&lt;/td&gt;&lt;td&gt;00010100&lt;/td&gt;&lt;td&gt;024&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;14&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;NAK&lt;/td&gt;&lt;td&gt;00010101&lt;/td&gt;&lt;td&gt;025&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;SYN&lt;/td&gt;&lt;td&gt;00010110&lt;/td&gt;&lt;td&gt;026&lt;/td&gt;&lt;td&gt;22&lt;/td&gt;&lt;td&gt;16&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ETB&lt;/td&gt;&lt;td&gt;00010111&lt;/td&gt;&lt;td&gt;027&lt;/td&gt;&lt;td&gt;23&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;CAN&lt;/td&gt;&lt;td&gt;00011000&lt;/td&gt;&lt;td&gt;030&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;td&gt;18&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;EM&lt;/td&gt;&lt;td&gt;00011001&lt;/td&gt;&lt;td&gt;031&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;td&gt;19&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;SUB&lt;/td&gt;&lt;td&gt;00011010&lt;/td&gt;&lt;td&gt;032&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;td&gt;1A&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;ESC&lt;/td&gt;&lt;td&gt;00011011&lt;/td&gt;&lt;td&gt;033&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;td&gt;1B&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;FS&lt;/td&gt;&lt;td&gt;00011100&lt;/td&gt;&lt;td&gt;034&lt;/td&gt;&lt;td&gt;28&lt;/td&gt;&lt;td&gt;1C&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;GS&lt;/td&gt;&lt;td&gt;00011101&lt;/td&gt;&lt;td&gt;035&lt;/td&gt;&lt;td&gt;29&lt;/td&gt;&lt;td&gt;1D&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;RS&lt;/td&gt;&lt;td&gt;00011110&lt;/td&gt;&lt;td&gt;036&lt;/td&gt;&lt;td&gt;30&lt;/td&gt;&lt;td&gt;1E&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td&gt;US&lt;/td&gt;&lt;td&gt;00011111&lt;/td&gt;&lt;td&gt;037&lt;/td&gt;&lt;td&gt;31&lt;/td&gt;&lt;td&gt;1F&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-8688519715257884867?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/8688519715257884867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=8688519715257884867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8688519715257884867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8688519715257884867'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/serial-programming-guide-for-posix_29.html' title='Serial Programming Guide for POSIX Operating Systems'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-4996482435324144598</id><published>2008-05-29T02:33:00.001-07:00</published><updated>2008-05-29T02:38:29.583-07:00</updated><title type='text'></title><content type='html'>&lt;pre&gt;&lt;span style="font-size:130%;"&gt; Linux Serial Port Programming Mini-Howto&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1. Introduction&lt;br /&gt;&lt;br /&gt;This document describes how to program the RS-232 ports for serial&lt;br /&gt;communications, under PC-Linux. It covers information about&lt;br /&gt;the serial ports, RS232 connections, modem issues, and the C programming&lt;br /&gt;logic.&lt;br /&gt;&lt;br /&gt;2. Background&lt;br /&gt;&lt;br /&gt;For our final year project, our group had to design a concept World&lt;br /&gt;Wide Web browser. Our prototype was a hand-held device which plugged&lt;br /&gt;into a PC's COM2 (25-pin) serial port. The user would issue commands&lt;br /&gt;to the browser (eg Back, Open, etc) by sending character commands to&lt;br /&gt;the PC. The browser software would detect it, and perform the required&lt;br /&gt;operation.&lt;br /&gt;&lt;br /&gt;The method provided in the 'Linux I/O port programming mini-HOWTO'&lt;br /&gt;did not act reliably. Often, an incorrect value would be received.&lt;br /&gt;The information within provided a 100% reliable, quasi-POSIX-compliant&lt;br /&gt;approach to communication.&lt;br /&gt;&lt;br /&gt;The program provided at the end of this 0 formed the basis of&lt;br /&gt;the PC's communication program. This document is written from the&lt;br /&gt;1 needed for the web browser project. It revolves around&lt;br /&gt;C programming for Linux, for a 9600 baud device attached to COM2.&lt;br /&gt;&lt;br /&gt;3. Acknowledgements&lt;br /&gt;&lt;br /&gt;The information here comes mainly from these sources -&lt;br /&gt;&lt;br /&gt;Heavily based on the 'Serial Programming Guide for POSIX Compliant&lt;br /&gt;Operating Systems', at http://www.easysw.com/~mike/serial/, by&lt;br /&gt;mike@easysw.com. If you need greater detail or more information, then&lt;br /&gt;this is the place to visit. Most of the information in this 0&lt;br /&gt;originated here.&lt;br /&gt;&lt;br /&gt;The 'Linux I/O port programming mini-HOWTO', by Riku Saikkonen&lt;br /&gt;(rjs@spider.compart.fi). This document provides a different approach&lt;br /&gt;to Linux serial programming.&lt;br /&gt;&lt;br /&gt;'The Linux Serial HOWTO', by Greg Hankins, greg.hankins@cc.gatech.edu&lt;br /&gt;describes how to set up serial communications devices on a Linux box.&lt;br /&gt;It describes many aspects of serial devices and 0.&lt;br /&gt;&lt;br /&gt;My two wonderful project partners: Gerel Enrile and Joyce Gong.&lt;br /&gt;&lt;br /&gt;4. Copyright&lt;br /&gt;&lt;br /&gt;This document is copyright (C) 1997 by Antonino Iannella.&lt;br /&gt;It is covered under the general Linux HOWTO copyright agreement.&lt;br /&gt;&lt;br /&gt;It is intended for the general public. it may be reproduced and&lt;br /&gt;distributed in whole or in part, using any electronic or physical&lt;br /&gt;medium. However, this copyright notice must remain on all copies.&lt;br /&gt;&lt;br /&gt;Please forward question, suggestions, corrections, and all tidbits&lt;br /&gt;of information to the author at antonino@usa.net&lt;br /&gt;(or nettuno@light.iinet.net.au).&lt;br /&gt;You will be acknowledged in future HOWTO revisions.&lt;br /&gt;&lt;br /&gt;5. RS-232 connections&lt;br /&gt;&lt;br /&gt;RS-232 is a standard for serial communications. It comes in different&lt;br /&gt;varieties. The most common is RS-232C which defines a 'mark' bit as a&lt;br /&gt;voltage between -3V and -12V, and a 'space' bit as a voltage between&lt;br /&gt;+3V and +12V. RS-574 is the standard for 9-pin PC connectors and&lt;br /&gt;voltages.&lt;br /&gt;&lt;br /&gt;RS-232 basically consists of wires for serial communications; sending&lt;br /&gt;and receiving, timing, status, and handshaking.&lt;br /&gt;You can use a null modem cable as your connector.&lt;br /&gt;The following pins are what were used for our project.  We connected&lt;br /&gt;the device to the DB-25 pin COM2 port. Please note that the Transmit&lt;br /&gt;line from the PC must connect to the Receive line of the device, and&lt;br /&gt;vice versa. Also, please note that a parallel port is different to a&lt;br /&gt;serial port!&lt;br /&gt;&lt;br /&gt;                        PC's pins   Device's pins&lt;br /&gt;    TxD   Transmit Data         2 - 3       RxD   Receive Data&lt;br /&gt;    RxD   Receive Data          3 - 2       TxD   Transmit Data&lt;br /&gt;    SG    Signal Ground         7 - 7       SG    Signal Ground&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Refer to the Linux Serial HOWTO for more specialised connections, and&lt;br /&gt;detailed RS-232 pins.&lt;br /&gt;&lt;br /&gt;6. Serial 0 and RS-232 definitions&lt;br /&gt;&lt;br /&gt;The way that data get transmitted in serial communications is, well,&lt;br /&gt;serially. One data bit is sent at a time. Each bit is either on (or the&lt;br /&gt;'mark' state), or off (or the 'space' state).&lt;br /&gt;&lt;br /&gt;The serial data throughput is usually expressed in bits-per-second (bps)&lt;br /&gt;or baudot (baud). Throughput is the number of data bits (2 or off) that&lt;br /&gt;may be sent in a second. Your modem might be able to support 115200 baud.&lt;br /&gt;The project's web browser device was designed to run at 9600 baud.&lt;br /&gt;&lt;br /&gt;RS-232 provides 18 different signals. About 6 are available to UNIX for&lt;br /&gt;programming.&lt;br /&gt;&lt;br /&gt;GND - Logic ground&lt;br /&gt;&lt;br /&gt;      Very important. Acts as a reference voltage, so the devices know&lt;br /&gt;      the relative voltage of the data transmitted.&lt;br /&gt;    &lt;br /&gt;TxD - Transmitted data&lt;br /&gt;&lt;br /&gt;      Carries the data transmitted from your PC.&lt;br /&gt;      A 'mark' voltage is interpreted as 1,&lt;br /&gt;      while a 'space' voltage is interpreted as 0.&lt;br /&gt;    &lt;br /&gt;RxD - Received data&lt;br /&gt;&lt;br /&gt;      Carries the data transmitted to your PC from the other device.&lt;br /&gt;    &lt;br /&gt;DCD - Data carrier detect&lt;br /&gt;&lt;br /&gt;      Is sent from the other device to your PC. A 'space' voltage means&lt;br /&gt;      that the device is still connected, or 'on-line'. This signal is&lt;br /&gt;      not always used or available.&lt;br /&gt;    &lt;br /&gt;DTR - Data terminal ready&lt;br /&gt;&lt;br /&gt;      Is sent from your PC to tell the device that you are ready (space)&lt;br /&gt;      or not-ready (mark). DTR is usually enabled automatically whenever&lt;br /&gt;      you access the serial interface.&lt;br /&gt;    &lt;br /&gt;CTS - Clear to send&lt;br /&gt;&lt;br /&gt;      Is sent from the other device to your PC.&lt;br /&gt;      A 'space' voltage means that your PC may send some data.&lt;br /&gt;      It is usually used to regulate the flow of serial data from your&lt;br /&gt;      PC, but it is not currently supported by all UNIX flavours.&lt;br /&gt;    &lt;br /&gt;RTS - Request to send&lt;br /&gt;&lt;br /&gt;      Is set to the 'space' voltage by your PC when it requests to send&lt;br /&gt;      more data. It also used to regulate data flow. Many systems leave&lt;br /&gt;      it on 'space' voltage all the time.&lt;br /&gt;    &lt;br /&gt;7. Communication issues&lt;br /&gt;&lt;br /&gt;This section covers other issues of serial communication which might be&lt;br /&gt;relevant to your particular application.&lt;br /&gt;Since we are programming for asynchronous communication, we need the&lt;br /&gt;PCs/devices to know where each character starts and ends in the serial&lt;br /&gt;data flow.&lt;br /&gt;&lt;br /&gt;In asynchronous mode, the serial data line stays in the mark state until&lt;br /&gt;a character is sent. A 'start bit' is sent before each character; it is&lt;br /&gt;always 0 and tells the PC/device that a character will follow.&lt;br /&gt;After the start bit, the character's bits are sent, then a 'parity' bit,&lt;br /&gt;and one or more stop bits.&lt;br /&gt;&lt;br /&gt;The parity bit is a checksum of the data bits, indicating the number of&lt;br /&gt;1 bits it contained -&lt;br /&gt;&lt;br /&gt;   Even parity  - parity bit is 1 if there is an even number of 1s&lt;br /&gt;   Odd parity   - parity bit is 1 if there is an odd number of 1s&lt;br /&gt;   Space parity - parity bit is always 0&lt;br /&gt;   Mark parity  - parity bit is 1&lt;br /&gt;   No parity    - no parity bit is sent or present.&lt;br /&gt;&lt;br /&gt;'Stop' bits come at the end of every character. There may be 1, 1.5, or 2&lt;br /&gt;stop bits. They used to be used to give the computer time to process the&lt;br /&gt;character, but now they are used to synchronise the computer to the&lt;br /&gt;incoming characters.&lt;br /&gt;&lt;br /&gt;Asynchronous data is usually described like '8N1' - 8 data bits, no parity&lt;br /&gt;bits, 1 stop bit. Another common one is '7N1'.&lt;br /&gt;&lt;br /&gt;Flow control is used to regulate the data flow between devices, if there&lt;br /&gt;is some sort of limitation, such as a slow device. There is 'Software&lt;br /&gt;Flow Control' using special characters, XON and XOFF, to regulate the flow.&lt;br /&gt;This method is not useful for transmitting non-textual data.&lt;br /&gt;'Hardware Flow Control' uses the RTS and CTS signals instead of special&lt;br /&gt;characters. The receiver sets CTS to space when it is ready to receive,&lt;br /&gt;and to mark when it's not. The sender uses RTS the same way. This method&lt;br /&gt;is faster than Software Flow Control, since it uses a separate set of&lt;br /&gt;signals instead of extra bits.&lt;br /&gt;&lt;br /&gt;Since the receive or transmit signal is at mark voltage until a new character&lt;br /&gt;is sent. A 'break' condition exists when the line is set to low for 1/4&lt;br /&gt;to 1/2 a second. It is used to reset a communications line, or change&lt;br /&gt;the operation mode of devices like modems.&lt;br /&gt;&lt;br /&gt;8. Basic port programming&lt;br /&gt;&lt;br /&gt;Hopefully, all of the above is reasonably clear to you, so you may proceed&lt;br /&gt;to program with confidence!&lt;br /&gt;&lt;br /&gt;In UNIX all system devices are treated as (special) files. All serial ports&lt;br /&gt;are opened, read from, written to, and closed, just like a binary file.&lt;br /&gt;In Linux, the PC serial ports are&lt;br /&gt;&lt;br /&gt;   COM1 - /dev/ttyS0&lt;br /&gt;   COM2 - /dev/ttyS1&lt;br /&gt;   COM3 - /dev/ttyS2&lt;br /&gt;   COM4 - /dev/ttyS3&lt;br /&gt;&lt;br /&gt;Firstly, open the serial port as a file. However, UNIX does not allow&lt;br /&gt;devices to be accessed by normal users. To solve this, either run the&lt;br /&gt;program as the superuser, or change the permission on the device as root,&lt;br /&gt;eg&lt;br /&gt;&lt;br /&gt;   chmod a+rw /dev/ttyS1          (lets everyone access COM2)&lt;br /&gt;&lt;br /&gt;To open the file do the following. Notice the three flags used in the&lt;br /&gt;open() function. O_RDWR means that we open the port for reading and&lt;br /&gt;writing. O_NOCTTY specifies that the program won't be the controlling&lt;br /&gt;entity for the port. Most user programs don't want this feature.&lt;br /&gt;O_NDELAY means that your program ignores the DCD line. If it didn't,&lt;br /&gt;the program will be put to sleep until DCD is set to 'space' voltage.&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* 'open_port()' - Open serial port 1 - COM2.&lt;br /&gt;*&lt;br /&gt;* Returns the file descriptor on success or -1 on error.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;int open_port(void)&lt;br /&gt;{&lt;br /&gt; int fd;                                   /* File descriptor for the port */&lt;br /&gt;&lt;br /&gt; fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt; if (fd == -1)&lt;br /&gt; {                                              /* Could not open the port */&lt;br /&gt;   fprintf(stderr, "open_port: Unable to open /dev/ttyS1 - %s\n",&lt;br /&gt;           strerror(errno));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return (fd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;If you need to write data to the port, do something like&lt;br /&gt;&lt;br /&gt; n = write(fd, "ATZ\r", 4);&lt;br /&gt;&lt;br /&gt; if (n &lt;&gt; and access the termios structure using the&lt;br /&gt;POSIX tcgetattr() and tcsetattr() functions.&lt;br /&gt;&lt;br /&gt;The termios structure contains&lt;br /&gt;&lt;br /&gt; c_cflag - Control options&lt;br /&gt; c_lflag - Line options&lt;br /&gt; c_iflag - Input options&lt;br /&gt; c_oflag - Output options&lt;br /&gt; c_cc    - Control characters&lt;br /&gt;&lt;br /&gt;See section 12 for a list of c_cflag control modes.&lt;br /&gt;They are used to set the baud rate, parity and stop bits, and flow control.&lt;br /&gt;Always enable CLOCAL and CREAD, so the program does not own the port, and so&lt;br /&gt;the serial interface driver will read incoming bytes.&lt;br /&gt;&lt;br /&gt;9.1. Accessing the termios structure and the baud rate&lt;br /&gt;&lt;br /&gt;Use cfsetospeed() and cfsetispeed() to set the baud rate.&lt;br /&gt;CRTSCTS might be called CNEW_RTSCTS on other systems.&lt;br /&gt;The following uses a termios structure called 'options'.&lt;br /&gt;For our project, the device transmitted at 9600 baud and transmitted nothing&lt;br /&gt;special.&lt;br /&gt;&lt;br /&gt;tcgetattr(mainfd, &amp;amp;options);        /* Get the current options for the port */&lt;br /&gt;cfsetispeed(&amp;amp;options, B9600);                 /* Set the baud rates to 9600 */&lt;br /&gt;cfsetospeed(&amp;amp;options, B9600);  &lt;br /&gt;                                 /* Enable the receiver and set local mode */&lt;br /&gt;options.c_cflag |= (CLOCAL | CREAD);&lt;br /&gt;   &lt;br /&gt;                                      /* Set the new options for the port */&lt;br /&gt;tcsetattr(mainfd, TCSANOW, &amp;amp;options);&lt;br /&gt;&lt;br /&gt;The tcsetattr() function replaces the port's termios structure with the&lt;br /&gt;settings you provided. The TCSANOW constant means that the changes should&lt;br /&gt;occur immediately, without waiting for data transmission to complete.&lt;br /&gt;Alternative choices are TCSADRAIN and TCSAFLUSH, which wait until buffers&lt;br /&gt;are cleared. Refer to section 13.&lt;br /&gt;&lt;br /&gt;9.2. Character size and parity&lt;br /&gt;&lt;br /&gt;To set the character size, you must use bitwise logic.&lt;br /&gt;The following code sets the character size to 8 data bits, and no parity.&lt;br /&gt;                     &lt;br /&gt;  options.c_cflag &amp;amp;= ~PARENB;  /* Mask character size to 8 bits, no parity */&lt;br /&gt;  options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;  options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;  options.c_cflag |=  CS8;                           /* Select 8 data bits */&lt;br /&gt;&lt;br /&gt;For other methods, refer to section 11.&lt;br /&gt;&lt;br /&gt;9.3. Hardware flow control&lt;br /&gt;&lt;br /&gt;To enable hardware flow control, use&lt;br /&gt;&lt;br /&gt;   options.c_cflag |= CRTSCTS;            /* Enable hardware flow control */&lt;br /&gt;&lt;br /&gt;To disable it,&lt;br /&gt;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CRTSCTS;          /* Disable hardware flow control */&lt;br /&gt;&lt;br /&gt;9.4. Canonical and raw input&lt;br /&gt;&lt;br /&gt;Canonical input means that all incoming characters are placed in a buffer&lt;br /&gt;which may be edited by the user, until a carriage return or line feed (CR or&lt;br /&gt;LF) are received. Typically, you would use&lt;br /&gt;&lt;br /&gt;options.c_lflag |= ~(ICANON | ECHO | ECHOE);&lt;br /&gt;&lt;br /&gt;Raw input is unprocessed, so they may be used as they are read.&lt;br /&gt;Our device sent raw data.&lt;br /&gt;&lt;br /&gt;options.c_lflag &amp;amp;= ~(ICANON | ECHO | ISIG);&lt;br /&gt;&lt;br /&gt;Whether you use canonical or raw input, make sure you never enable input&lt;br /&gt;echo when connected to a computer/device which is echoing characters to you.&lt;br /&gt;Refer to section 14 for local mode constants.&lt;br /&gt;&lt;br /&gt;9.5. POSIX input modes&lt;br /&gt;&lt;br /&gt;Set the port's input modes for any input processing.&lt;br /&gt;Set input parity when you have enabled parity in the c_cflag part.&lt;br /&gt;Usually you'd use the following to enable parity checking, and strip the&lt;br /&gt;parity bit off the data, before your program reads it.&lt;br /&gt;&lt;br /&gt;options.c_iflag |= (INPCK | ISTRIP);&lt;br /&gt;&lt;br /&gt;You might use IGNPAR, which ignores all parity errors. PARMRK marks parity&lt;br /&gt;errors by inserting a DEL(255) and NUL character before the bad character.&lt;br /&gt;If IGNPAR is enabled, only a NUL is inserted.&lt;br /&gt;&lt;br /&gt;You may set software flow control using&lt;br /&gt;&lt;br /&gt;options.c_iflag |= (IXON | IXOFF | IXANY);&lt;br /&gt;&lt;br /&gt;Refer to section 15 for input mode constants.&lt;br /&gt;&lt;br /&gt;9.6. POSIX output modes&lt;br /&gt;&lt;br /&gt;To set port output modes, use the c_oflag member.&lt;br /&gt;To select processed output, use the following. Of all the output modes, you&lt;br /&gt;will probably only use ONCLR to convert newlines into CR and LFs.&lt;br /&gt;&lt;br /&gt;options.c_oflag |= OPOST;&lt;br /&gt;&lt;br /&gt;For raw output, use&lt;br /&gt;&lt;br /&gt;options.c_oflag &amp;amp;= ~OPOST;&lt;br /&gt;&lt;br /&gt;Refer to section 16 for output mode constants.&lt;br /&gt;&lt;br /&gt;9.7. POSIX control modes&lt;br /&gt;&lt;br /&gt;You may set the control characters using the c_cc part.&lt;br /&gt;Set the software flow control characters in the VSTART and VSTOP&lt;br /&gt;elements. The standard is DC1(17) and DC3(19) for XON and XOFF.&lt;br /&gt;VMIN specifies the minimum number of 0 to read. If it is 0, then&lt;br /&gt;VTIME specifies the time to wait for each character.&lt;br /&gt;If VMIN is not 0, VTIME is the time to wait to read the first character.&lt;br /&gt;If the first character is read, then any read() will be blocked until all&lt;br /&gt;VMIN characters are read.&lt;br /&gt;VTIME is specified in tenths of seconds. If it is 0, then read()s will&lt;br /&gt;be permanently blocked unless NDELAY was previously specified with fcntl().&lt;br /&gt;&lt;br /&gt;Refer to section 17 for control mode constants.&lt;br /&gt;&lt;br /&gt;10. Sample program&lt;br /&gt;&lt;br /&gt;This program is a skeleton COM2 reader, which was used for our project.&lt;br /&gt;It did not need all of the information specified above for&lt;br /&gt;configuring ports. The 20ms delay is used to indicate that data coming into&lt;br /&gt;the port is buffered, and is available for the next read().&lt;br /&gt;&lt;br /&gt;/* Better port reading program&lt;br /&gt; v1.0&lt;br /&gt; 23-10-96&lt;br /&gt;&lt;br /&gt; This test program uses quasi-POSIX compliant UNIX functions to&lt;br /&gt; open the ABU port and read.&lt;br /&gt;&lt;br /&gt; Uses termio functions to initialise the port to 9600 baud, at&lt;br /&gt; 8 data bits, no parity, no hardware flow control,&lt;br /&gt; and features character buffering.&lt;br /&gt; The 20ms delay after the port read indicates that characters are&lt;br /&gt; buffered if a button is pressed many times.&lt;br /&gt;&lt;br /&gt; This program was derived from instructions at&lt;br /&gt;  http://www.easysw.com/~mike/serial/&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;&lt;/termios.h&gt;&lt;/span&gt; #include stdio.h'   /* Standard input/output definitions */&lt;br /&gt;#include string.h  /* String function definitions */&lt;br /&gt;#include unistd.h  /* UNIX standard function definitions */&lt;br /&gt;#include fcntl.h   /* File control definitions */&lt;br /&gt;#include errno.h   /* Error number definitions */&lt;br /&gt;#include termios.h /* POSIX terminal control definitions */&lt;span style="font-size:130%;"&gt;&lt;termios.h&gt;&lt;stdio.h&gt;&lt;string.h&gt;&lt;unistd.h&gt;&lt;fcntl.h&gt;&lt;errno.h&gt;&lt;termios.h&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;* 'open_port()' - Open serial port 1.&lt;br /&gt;*&lt;br /&gt;* Returns the file descriptor on success or -1 on error.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;int open_port(void)&lt;br /&gt;{&lt;br /&gt; int fd;                                   /* File descriptor for the port */&lt;br /&gt;&lt;br /&gt; fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt;&lt;br /&gt; if (fd == -1)&lt;br /&gt; {                                              /* Could not open the port */&lt;br /&gt;   fprintf(stderr, "open_port: Unable to open /dev/ttyS1 - %s\n",&lt;br /&gt;           strerror(errno));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return (fd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;{&lt;br /&gt;int mainfd=0;                                            /* File descriptor */&lt;br /&gt;char chout;&lt;br /&gt;struct termios options;&lt;br /&gt;&lt;br /&gt;mainfd = open_port();&lt;br /&gt;&lt;br /&gt;fcntl(mainfd, F_SETFL, FNDELAY);                  /* Configure port reading */&lt;br /&gt;                                   /* Get the current options for the port */&lt;br /&gt;tcgetattr(mainfd, &amp;amp;options);&lt;br /&gt;cfsetispeed(&amp;amp;options, B9600);                 /* Set the baud rates to 9600 */&lt;br /&gt;cfsetospeed(&amp;amp;options, B9600);&lt;br /&gt;&lt;br /&gt;                                 /* Enable the receiver and set local mode */&lt;br /&gt;options.c_cflag |= (CLOCAL | CREAD);&lt;br /&gt;options.c_cflag &amp;amp;= ~PARENB; /* Mask the character size to 8 bits, no parity */&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |=  CS8;                              /* Select 8 data bits */&lt;br /&gt;options.c_cflag &amp;amp;= ~CRTSCTS;               /* Disable hardware flow control */&lt;br /&gt;&lt;br /&gt;                               /* Enable data to be processed as raw input */&lt;br /&gt;options.c_lflag &amp;amp;= ~(ICANON | ECHO | ISIG);&lt;br /&gt;   &lt;br /&gt;                                      /* Set the new options for the port */&lt;br /&gt;tcsetattr(mainfd, TCSANOW, &amp;amp;options);&lt;br /&gt;                     &lt;br /&gt;while (1)&lt;br /&gt;{&lt;br /&gt; read(mainfd, &amp;amp;chout, sizeof(chout));          /* Read character from ABU */&lt;br /&gt;&lt;br /&gt; if (chout != 0)&lt;br /&gt;    printf("Got %c.\n", chout);&lt;br /&gt;&lt;br /&gt; chout=0;&lt;br /&gt; usleep(20000);&lt;br /&gt;}&lt;br /&gt;                                                  /* Close the serial port */&lt;br /&gt;close(mainfd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;11. Character and parity settings&lt;br /&gt;&lt;br /&gt;  No parity (8N1):&lt;br /&gt;&lt;br /&gt;   options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |= CS8;&lt;br /&gt;&lt;br /&gt;  Even parity (7E1):&lt;br /&gt;&lt;br /&gt;   options.c_cflag |= PARENB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~PARODD;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;  Odd parity (7O1):&lt;br /&gt;&lt;br /&gt;   options.c_cflag |= PARENB;&lt;br /&gt;   options.c_cflag |= PARODD;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;  Mark parity is simulated by using 2 stop bits (7M1):&lt;br /&gt;&lt;br /&gt;   options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;   options.c_cflag |= CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;  Space parity is setup the same as no parity (7S1):&lt;br /&gt;&lt;br /&gt;   options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |= CS8;&lt;br /&gt;&lt;br /&gt;12. POSIX control mode flags&lt;br /&gt;&lt;br /&gt;The following table lists the possible control modes for c_cflag.&lt;br /&gt;&lt;br /&gt; Constant     Description&lt;br /&gt; ________________________&lt;br /&gt;&lt;br /&gt; CBAUD        Bit mask for baud rate       &lt;br /&gt; B0           0 baud (drop DTR)       &lt;br /&gt; B50          50 baud       &lt;br /&gt; B75          75 baud       &lt;br /&gt; B110         110 baud       &lt;br /&gt; B134         134.5 baud       &lt;br /&gt; B150         150 baud       &lt;br /&gt; B200         200 baud       &lt;br /&gt; B300         300 baud       &lt;br /&gt; B600         600 baud       &lt;br /&gt; B1200        1200 baud       &lt;br /&gt; B1800        1800 baud       &lt;br /&gt; B2400        2400 baud       &lt;br /&gt; B4800        4800 baud       &lt;br /&gt; B9600        9600 baud       &lt;br /&gt; B19200       19200 baud       &lt;br /&gt; B38400       38400 baud       &lt;br /&gt; EXTA         External rate clock       &lt;br /&gt; EXTB         External rate clock       &lt;br /&gt; CSIZE        Bit mask for data bits       &lt;br /&gt; CS5          5 data bits       &lt;br /&gt; CS6          6 data bits       &lt;br /&gt; CS7          7 data bits       &lt;br /&gt; CS8          8 data bits       &lt;br /&gt; CSTOPB       2 stop bits (1 otherwise)       &lt;br /&gt; CREAD        Enable receiver       &lt;br /&gt; PARENB       Enable parity bit       &lt;br /&gt; PARODD       Use odd parity instead of even       &lt;br /&gt; HUPCL        Hangup (drop DTR) on last close       &lt;br /&gt; CLOCAL       Local line - do not change 'owner' of port    &lt;br /&gt; LOBLK        Block job control output       &lt;br /&gt; CRTSCTS      Enable hardware flow control (not supported on all platforms)       &lt;br /&gt;&lt;br /&gt;13. POSIX tcsetattr Constants&lt;br /&gt;&lt;br /&gt; Constant   Description&lt;br /&gt; ______________________&lt;br /&gt;&lt;br /&gt; TCSANOW    Make changes now without waiting for data to complete&lt;br /&gt; TCSADRAIN  Wait until everything has been transmitted&lt;br /&gt; TCSAFLUSH  Flush input and output buffers and make the change&lt;br /&gt;&lt;br /&gt;14. POSIX Local Mode Constants&lt;br /&gt;&lt;br /&gt; Constant   Description&lt;br /&gt; ______________________&lt;br /&gt;&lt;br /&gt; ISIG       Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals&lt;br /&gt; ICANON     Enable canonical input (else raw)&lt;br /&gt; XCASE      Map uppercase \lowercase (obselete)&lt;br /&gt; ECHO       Enable echoing of input characters&lt;br /&gt; ECHOE      Echo erase character as BS-SP-BS&lt;br /&gt; ECHOK      Echo NL after kill character&lt;br /&gt; ECHONL     Echo NL&lt;br /&gt; NOFLSH     Disable flushing of input buffers after interrupt&lt;br /&gt;            or quit characters&lt;br /&gt; IEXTEN     Enable extended functions&lt;br /&gt; ECHOCTL    Echo control characters as ^char and delete as ~?&lt;br /&gt; ECHOPRT    Echo erased character as character erased&lt;br /&gt; ECHOKE     BS-SP-BS entire line on line kill&lt;br /&gt; FLUSHO     Output being flushed&lt;br /&gt; PENDIN     Retype pending input at next read or input char&lt;br /&gt; TOSTOP     Send SIGTTOU for background output&lt;br /&gt;&lt;br /&gt;15. POSIX Input Mode Constants&lt;br /&gt;&lt;br /&gt; Constant   Description&lt;br /&gt; ______________________&lt;br /&gt;&lt;br /&gt; INPCK      Enable parity check&lt;br /&gt; IGNPAR     Ignore parity errors&lt;br /&gt; PARMRK     Mark parity errors&lt;br /&gt; ISTRIP     Strip parity bits&lt;br /&gt; IXON       Enable software flow control (outgoing)&lt;br /&gt; IXOFF      Enable software flow control (incoming)&lt;br /&gt; IXANY      Allow any character to start flow again&lt;br /&gt; IGNBRK     Ignore break condition&lt;br /&gt; BRKINT     Send a SIGINT when a break condition is detected&lt;br /&gt; INLCR      Map NL to CR&lt;br /&gt; IGNCR      Ignore CR&lt;br /&gt; ICRNL      Map CR to NL&lt;br /&gt; IUCLC      Map uppercase to lowercase&lt;br /&gt; IMAXBEL    Echo BEL on input line too long&lt;br /&gt;&lt;br /&gt;16. POSIX Output Mode Constants&lt;br /&gt;&lt;br /&gt; Constant   Description&lt;br /&gt; ______________________&lt;br /&gt;&lt;br /&gt; OPOST      Postprocess output (not set = raw output)&lt;br /&gt; OLCUC      Map lowercase to uppercase&lt;br /&gt; ONLCR      Map NL to CR-NL&lt;br /&gt; OCRNL      Map CR to NL&lt;br /&gt; NOCR       No CR output at column 0&lt;br /&gt; ONLRET     NL performs CR function&lt;br /&gt; OFILL      Use fill characters for delay&lt;br /&gt; OFDEL      Fill character is DEL&lt;br /&gt; NLDLY      Mask for delay time needed between lines&lt;br /&gt; NL0        No delay for NLs&lt;br /&gt; NL1        Delay further output after newline for 100 milliseconds&lt;br /&gt; CRDLY      Mask for delay time needed to return carriage to left column&lt;br /&gt; CR0        No delay for CRs&lt;br /&gt; CR1        Delay after CRs depending on current column position&lt;br /&gt; CR2        Delay 100 milliseconds after sending CRs&lt;br /&gt; CR3        Delay 150 milliseconds after sending CRs&lt;br /&gt; TABDLY     Mask for delay time needed after TABs&lt;br /&gt; TAB0       No delay for TABs&lt;br /&gt; TAB1       Delay after TABs depending on current column position&lt;br /&gt; TAB2       Delay 100 milliseconds after sending TABs&lt;br /&gt; TAB3       Expand TAB characters to spaces&lt;br /&gt; BSDLY      Mask for delay time needed after BSs&lt;br /&gt; BS0        No delay for BSs&lt;br /&gt; BS1        Delay 50 milliseconds after sending BSs&lt;br /&gt; VTDLY      Mask for delay time needed after VTs&lt;br /&gt; VT0        No delay for VTs&lt;br /&gt; VT1        Delay 2 seconds after sending VTs&lt;br /&gt; FFDLY      Mask for delay time needed after FFs&lt;br /&gt; FF0        No delay for FFs&lt;br /&gt; FF1        Delay 2 seconds after sending FFs&lt;br /&gt;&lt;br /&gt;17. POSIX Control Character Constants&lt;br /&gt;&lt;br /&gt; Constant   Description          Key&lt;br /&gt; ______________________________________&lt;br /&gt;&lt;br /&gt; VINTR      Interrupt            CTRL-C&lt;br /&gt; VQUIT      Quit                 CTRL-Z&lt;br /&gt; VERASE     Erase                Backspace (BS)&lt;br /&gt; VKILL      Kill-line            CTRL-U&lt;br /&gt; VEOF       End-of-file          CTRL-D&lt;br /&gt; VEOL       End-of-line          Carriage return (CR)&lt;br /&gt; VEOL2      Second end-of-line   Line feed (LF)&lt;br /&gt; VMIN       Minimum number of characters to read&lt;br /&gt; VTIME      Time to wait for data (tenths of seconds)&lt;br /&gt;&lt;br /&gt;----------------- End of Linux Serial Programming Mini-Howto -----------------&lt;/termios.h&gt;&lt;/errno.h&gt;&lt;/fcntl.h&gt;&lt;/unistd.h&gt;&lt;/string.h&gt;&lt;/stdio.h&gt;&lt;/termios.h&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-4996482435324144598?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/4996482435324144598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=4996482435324144598' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/4996482435324144598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/4996482435324144598'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/linux-serial-port-programming-mini_29.html' title=''/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-6772549873399199987</id><published>2008-05-29T02:33:00.000-07:00</published><updated>2008-05-29T02:36:02.618-07:00</updated><title type='text'>Linux Serial Port Programming Mini-Howto</title><content type='html'>&lt;pre&gt;&lt;span style="font-size:130%;"&gt; Linux Serial Port Programming Mini-Howto&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; 1. Introduction&lt;br /&gt;&lt;br /&gt; This document describes how to program the RS-232 ports for serial&lt;br /&gt; communications, under PC-Linux. It covers information about&lt;br /&gt; the serial ports, RS232 connections, modem issues, and the C programming&lt;br /&gt; logic.&lt;br /&gt;&lt;br /&gt; 2. Background&lt;br /&gt;&lt;br /&gt; For our final year project, our group had to design a concept World&lt;br /&gt; Wide Web browser. Our prototype was a hand-held device which plugged&lt;br /&gt; into a PC's COM2 (25-pin) serial port. The user would issue commands&lt;br /&gt; to the browser (eg Back, Open, etc) by sending character commands to&lt;br /&gt; the PC. The browser software would detect it, and perform the required&lt;br /&gt; operation.&lt;br /&gt;&lt;br /&gt; The method provided in the 'Linux I/O port programming mini-HOWTO'&lt;br /&gt; did not act reliably. Often, an incorrect value would be received.&lt;br /&gt; The information within provided a 100% reliable, quasi-POSIX-compliant&lt;br /&gt; approach to communication.&lt;br /&gt;&lt;br /&gt; The program provided at the end of this 0 formed the basis of&lt;br /&gt; the PC's communication program. This document is written from the&lt;br /&gt; 1 needed for the web browser project. It revolves around&lt;br /&gt; C programming for Linux, for a 9600 baud device attached to COM2.&lt;br /&gt;&lt;br /&gt; 3. Acknowledgements&lt;br /&gt;&lt;br /&gt; The information here comes mainly from these sources -&lt;br /&gt;  &lt;br /&gt; Heavily based on the 'Serial Programming Guide for POSIX Compliant&lt;br /&gt; Operating Systems', at http://www.easysw.com/~mike/serial/, by&lt;br /&gt; mike@easysw.com. If you need greater detail or more information, then&lt;br /&gt; this is the place to visit. Most of the information in this 0&lt;br /&gt; originated here.&lt;br /&gt;  &lt;br /&gt; The 'Linux I/O port programming mini-HOWTO', by Riku Saikkonen&lt;br /&gt; (rjs@spider.compart.fi). This document provides a different approach&lt;br /&gt; to Linux serial programming.&lt;br /&gt;&lt;br /&gt; 'The Linux Serial HOWTO', by Greg Hankins, greg.hankins@cc.gatech.edu&lt;br /&gt; describes how to set up serial communications devices on a Linux box.&lt;br /&gt; It describes many aspects of serial devices and 0.&lt;br /&gt;&lt;br /&gt; My two wonderful project partners: Gerel Enrile and Joyce Gong.&lt;br /&gt;&lt;br /&gt; 4. Copyright&lt;br /&gt;&lt;br /&gt; This document is copyright (C) 1997 by Antonino Iannella.&lt;br /&gt; It is covered under the general Linux HOWTO copyright agreement.&lt;br /&gt;&lt;br /&gt; It is intended for the general public. it may be reproduced and&lt;br /&gt; distributed in whole or in part, using any electronic or physical&lt;br /&gt; medium. However, this copyright notice must remain on all copies.&lt;br /&gt;&lt;br /&gt; Please forward question, suggestions, corrections, and all tidbits&lt;br /&gt; of information to the author at antonino@usa.net&lt;br /&gt; (or nettuno@light.iinet.net.au).&lt;br /&gt; You will be acknowledged in future HOWTO revisions.&lt;br /&gt;&lt;br /&gt; 5. RS-232 connections&lt;br /&gt;&lt;br /&gt; RS-232 is a standard for serial communications. It comes in different&lt;br /&gt; varieties. The most common is RS-232C which defines a 'mark' bit as a&lt;br /&gt; voltage between -3V and -12V, and a 'space' bit as a voltage between&lt;br /&gt; +3V and +12V. RS-574 is the standard for 9-pin PC connectors and&lt;br /&gt; voltages.&lt;br /&gt;&lt;br /&gt; RS-232 basically consists of wires for serial communications; sending&lt;br /&gt; and receiving, timing, status, and handshaking.&lt;br /&gt; You can use a null modem cable as your connector.&lt;br /&gt; The following pins are what were used for our project.  We connected&lt;br /&gt; the device to the DB-25 pin COM2 port. Please note that the Transmit&lt;br /&gt; line from the PC must connect to the Receive line of the device, and&lt;br /&gt; vice versa. Also, please note that a parallel port is different to a&lt;br /&gt; serial port!&lt;br /&gt;&lt;br /&gt;                         PC's pins   Device's pins&lt;br /&gt;     TxD   Transmit Data         2 - 3       RxD   Receive Data&lt;br /&gt;     RxD   Receive Data          3 - 2       TxD   Transmit Data&lt;br /&gt;     SG    Signal Ground         7 - 7       SG    Signal Ground&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Refer to the Linux Serial HOWTO for more specialised connections, and&lt;br /&gt; detailed RS-232 pins.&lt;br /&gt;&lt;br /&gt; 6. Serial 0 and RS-232 definitions&lt;br /&gt;&lt;br /&gt; The way that data get transmitted in serial communications is, well,&lt;br /&gt; serially. One data bit is sent at a time. Each bit is either on (or the&lt;br /&gt; 'mark' state), or off (or the 'space' state).&lt;br /&gt;&lt;br /&gt; The serial data throughput is usually expressed in bits-per-second (bps)&lt;br /&gt; or baudot (baud). Throughput is the number of data bits (2 or off) that&lt;br /&gt; may be sent in a second. Your modem might be able to support 115200 baud.&lt;br /&gt; The project's web browser device was designed to run at 9600 baud.&lt;br /&gt;&lt;br /&gt; RS-232 provides 18 different signals. About 6 are available to UNIX for&lt;br /&gt; programming.&lt;br /&gt;&lt;br /&gt; GND - Logic ground&lt;br /&gt;&lt;br /&gt;       Very important. Acts as a reference voltage, so the devices know&lt;br /&gt;       the relative voltage of the data transmitted.&lt;br /&gt;      &lt;br /&gt; TxD - Transmitted data&lt;br /&gt;&lt;br /&gt;       Carries the data transmitted from your PC.&lt;br /&gt;       A 'mark' voltage is interpreted as 1,&lt;br /&gt;       while a 'space' voltage is interpreted as 0.&lt;br /&gt;      &lt;br /&gt; RxD - Received data&lt;br /&gt;&lt;br /&gt;       Carries the data transmitted to your PC from the other device.&lt;br /&gt;      &lt;br /&gt; DCD - Data carrier detect&lt;br /&gt;&lt;br /&gt;       Is sent from the other device to your PC. A 'space' voltage means&lt;br /&gt;       that the device is still connected, or 'on-line'. This signal is&lt;br /&gt;       not always used or available.&lt;br /&gt;      &lt;br /&gt; DTR - Data terminal ready&lt;br /&gt;&lt;br /&gt;       Is sent from your PC to tell the device that you are ready (space)&lt;br /&gt;       or not-ready (mark). DTR is usually enabled automatically whenever&lt;br /&gt;       you access the serial interface.&lt;br /&gt;      &lt;br /&gt; CTS - Clear to send&lt;br /&gt;&lt;br /&gt;       Is sent from the other device to your PC.&lt;br /&gt;       A 'space' voltage means that your PC may send some data.&lt;br /&gt;       It is usually used to regulate the flow of serial data from your&lt;br /&gt;       PC, but it is not currently supported by all UNIX flavours.&lt;br /&gt;      &lt;br /&gt; RTS - Request to send&lt;br /&gt;&lt;br /&gt;       Is set to the 'space' voltage by your PC when it requests to send&lt;br /&gt;       more data. It also used to regulate data flow. Many systems leave&lt;br /&gt;       it on 'space' voltage all the time.&lt;br /&gt;      &lt;br /&gt; 7. Communication issues&lt;br /&gt;&lt;br /&gt; This section covers other issues of serial communication which might be&lt;br /&gt; relevant to your particular application.&lt;br /&gt; Since we are programming for asynchronous communication, we need the&lt;br /&gt; PCs/devices to know where each character starts and ends in the serial&lt;br /&gt; data flow.&lt;br /&gt;&lt;br /&gt; In asynchronous mode, the serial data line stays in the mark state until&lt;br /&gt; a character is sent. A 'start bit' is sent before each character; it is&lt;br /&gt; always 0 and tells the PC/device that a character will follow.&lt;br /&gt; After the start bit, the character's bits are sent, then a 'parity' bit,&lt;br /&gt; and one or more stop bits.&lt;br /&gt;&lt;br /&gt; The parity bit is a checksum of the data bits, indicating the number of&lt;br /&gt; 1 bits it contained -&lt;br /&gt;&lt;br /&gt;    Even parity  - parity bit is 1 if there is an even number of 1s&lt;br /&gt;    Odd parity   - parity bit is 1 if there is an odd number of 1s&lt;br /&gt;    Space parity - parity bit is always 0&lt;br /&gt;    Mark parity  - parity bit is 1&lt;br /&gt;    No parity    - no parity bit is sent or present.&lt;br /&gt;&lt;br /&gt; 'Stop' bits come at the end of every character. There may be 1, 1.5, or 2&lt;br /&gt; stop bits. They used to be used to give the computer time to process the&lt;br /&gt; character, but now they are used to synchronise the computer to the&lt;br /&gt; incoming characters.&lt;br /&gt;&lt;br /&gt; Asynchronous data is usually described like '8N1' - 8 data bits, no parity&lt;br /&gt; bits, 1 stop bit. Another common one is '7N1'.&lt;br /&gt;&lt;br /&gt; Flow control is used to regulate the data flow between devices, if there&lt;br /&gt; is some sort of limitation, such as a slow device. There is 'Software&lt;br /&gt; Flow Control' using special characters, XON and XOFF, to regulate the flow.&lt;br /&gt; This method is not useful for transmitting non-textual data.&lt;br /&gt; 'Hardware Flow Control' uses the RTS and CTS signals instead of special&lt;br /&gt; characters. The receiver sets CTS to space when it is ready to receive,&lt;br /&gt; and to mark when it's not. The sender uses RTS the same way. This method&lt;br /&gt; is faster than Software Flow Control, since it uses a separate set of&lt;br /&gt; signals instead of extra bits.&lt;br /&gt;&lt;br /&gt; Since the receive or transmit signal is at mark voltage until a new character&lt;br /&gt; is sent. A 'break' condition exists when the line is set to low for 1/4&lt;br /&gt; to 1/2 a second. It is used to reset a communications line, or change&lt;br /&gt; the operation mode of devices like modems.&lt;br /&gt;&lt;br /&gt; 8. Basic port programming&lt;br /&gt;&lt;br /&gt; Hopefully, all of the above is reasonably clear to you, so you may proceed&lt;br /&gt; to program with confidence!&lt;br /&gt;&lt;br /&gt; In UNIX all system devices are treated as (special) files. All serial ports&lt;br /&gt; are opened, read from, written to, and closed, just like a binary file.&lt;br /&gt; In Linux, the PC serial ports are&lt;br /&gt;&lt;br /&gt;    COM1 - /dev/ttyS0&lt;br /&gt;    COM2 - /dev/ttyS1&lt;br /&gt;    COM3 - /dev/ttyS2&lt;br /&gt;    COM4 - /dev/ttyS3&lt;br /&gt;&lt;br /&gt; Firstly, open the serial port as a file. However, UNIX does not allow&lt;br /&gt; devices to be accessed by normal users. To solve this, either run the&lt;br /&gt; program as the superuser, or change the permission on the device as root,&lt;br /&gt; eg&lt;br /&gt;&lt;br /&gt;    chmod a+rw /dev/ttyS1          (lets everyone access COM2)&lt;br /&gt;&lt;br /&gt; To open the file do the following. Notice the three flags used in the&lt;br /&gt; open() function. O_RDWR means that we open the port for reading and&lt;br /&gt; writing. O_NOCTTY specifies that the program won't be the controlling&lt;br /&gt; entity for the port. Most user programs don't want this feature.&lt;br /&gt; O_NDELAY means that your program ignores the DCD line. If it didn't,&lt;br /&gt; the program will be put to sleep until DCD is set to 'space' voltage.&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt; * 'open_port()' - Open serial port 1 - COM2.&lt;br /&gt; *&lt;br /&gt; * Returns the file descriptor on success or -1 on error.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;int open_port(void)&lt;br /&gt;{&lt;br /&gt;  int fd;                                   /* File descriptor for the port */&lt;br /&gt;&lt;br /&gt;  fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt;  if (fd == -1)&lt;br /&gt;  {                                              /* Could not open the port */&lt;br /&gt;    fprintf(stderr, "open_port: Unable to open /dev/ttyS1 - %s\n",&lt;br /&gt;            strerror(errno));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return (fd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;If you need to write data to the port, do something like&lt;br /&gt;&lt;br /&gt;  n = write(fd, "ATZ\r", 4);&lt;br /&gt;&lt;br /&gt;  if (n &lt; 0)&lt;br /&gt;     puts("write() of 4 bytes failed!\n");&lt;br /&gt;&lt;br /&gt;Reading from the port is more complicated. If you open the port in 'raw&lt;br /&gt;data' mode (the norm), each read() returns the number of characters actually&lt;br /&gt;available in the serial buffers. However, if no characters are available,&lt;br /&gt;read() will block until it receives characters, an interval timer expires,&lt;br /&gt;or an error occurs. Use the following to make read return immediately.&lt;br /&gt;FNDELAY makes read() return 0 if no characters were read.&lt;br /&gt;&lt;br /&gt;  fcntl(mainfd, F_SETFL, FNDELAY);             /* Configure port reading */&lt;br /&gt;&lt;br /&gt;To close the serial port, simply use&lt;br /&gt;&lt;br /&gt;  close(fd);&lt;br /&gt;&lt;br /&gt;9. Port configuration&lt;br /&gt;&lt;br /&gt;This section discusses how to configure the serial port for your device.&lt;br /&gt;You will need to set the terminal attributes related to the port.&lt;br /&gt;To do this, include &lt;termios.h&gt; and access the termios structure using the&lt;br /&gt;POSIX tcgetattr() and tcsetattr() functions.&lt;br /&gt;&lt;br /&gt;The termios structure contains&lt;br /&gt;&lt;br /&gt;  c_cflag - Control options&lt;br /&gt;  c_lflag - Line options&lt;br /&gt;  c_iflag - Input options&lt;br /&gt;  c_oflag - Output options&lt;br /&gt;  c_cc    - Control characters&lt;br /&gt; &lt;br /&gt;See section 12 for a list of c_cflag control modes.&lt;br /&gt;They are used to set the baud rate, parity and stop bits, and flow control.&lt;br /&gt;Always enable CLOCAL and CREAD, so the program does not own the port, and so&lt;br /&gt;the serial interface driver will read incoming bytes.&lt;br /&gt;&lt;br /&gt;9.1. Accessing the termios structure and the baud rate&lt;br /&gt;&lt;br /&gt;Use cfsetospeed() and cfsetispeed() to set the baud rate.&lt;br /&gt;CRTSCTS might be called CNEW_RTSCTS on other systems.&lt;br /&gt;The following uses a termios structure called 'options'.&lt;br /&gt;For our project, the device transmitted at 9600 baud and transmitted nothing&lt;br /&gt;special.&lt;br /&gt;&lt;br /&gt;tcgetattr(mainfd, &amp;amp;options);        /* Get the current options for the port */&lt;br /&gt;cfsetispeed(&amp;amp;options, B9600);                 /* Set the baud rates to 9600 */&lt;br /&gt;cfsetospeed(&amp;amp;options, B9600);   &lt;br /&gt;                                  /* Enable the receiver and set local mode */&lt;br /&gt;options.c_cflag |= (CLOCAL | CREAD);&lt;br /&gt;     &lt;br /&gt;                                       /* Set the new options for the port */&lt;br /&gt;tcsetattr(mainfd, TCSANOW, &amp;amp;options);&lt;br /&gt;&lt;br /&gt;The tcsetattr() function replaces the port's termios structure with the&lt;br /&gt;settings you provided. The TCSANOW constant means that the changes should&lt;br /&gt;occur immediately, without waiting for data transmission to complete.&lt;br /&gt;Alternative choices are TCSADRAIN and TCSAFLUSH, which wait until buffers&lt;br /&gt;are cleared. Refer to section 13.&lt;br /&gt;&lt;br /&gt;9.2. Character size and parity&lt;br /&gt;&lt;br /&gt;To set the character size, you must use bitwise logic.&lt;br /&gt;The following code sets the character size to 8 data bits, and no parity.&lt;br /&gt;                       &lt;br /&gt;   options.c_cflag &amp;amp;= ~PARENB;  /* Mask character size to 8 bits, no parity */&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;   options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;   options.c_cflag |=  CS8;                           /* Select 8 data bits */&lt;br /&gt;&lt;br /&gt;For other methods, refer to section 11.&lt;br /&gt;&lt;br /&gt;9.3. Hardware flow control&lt;br /&gt;&lt;br /&gt;To enable hardware flow control, use&lt;br /&gt;&lt;br /&gt;    options.c_cflag |= CRTSCTS;            /* Enable hardware flow control */ &lt;br /&gt;&lt;br /&gt;To disable it,&lt;br /&gt;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CRTSCTS;          /* Disable hardware flow control */ &lt;br /&gt;&lt;br /&gt;9.4. Canonical and raw input&lt;br /&gt;&lt;br /&gt;Canonical input means that all incoming characters are placed in a buffer&lt;br /&gt;which may be edited by the user, until a carriage return or line feed (CR or&lt;br /&gt;LF) are received. Typically, you would use&lt;br /&gt;&lt;br /&gt; options.c_lflag |= ~(ICANON | ECHO | ECHOE);&lt;br /&gt;&lt;br /&gt;Raw input is unprocessed, so they may be used as they are read.&lt;br /&gt;Our device sent raw data.&lt;br /&gt;&lt;br /&gt; options.c_lflag &amp;amp;= ~(ICANON | ECHO | ISIG);&lt;br /&gt;&lt;br /&gt;Whether you use canonical or raw input, make sure you never enable input&lt;br /&gt;echo when connected to a computer/device which is echoing characters to you.&lt;br /&gt;Refer to section 14 for local mode constants.&lt;br /&gt;&lt;br /&gt;9.5. POSIX input modes&lt;br /&gt;&lt;br /&gt;Set the port's input modes for any input processing.&lt;br /&gt;Set input parity when you have enabled parity in the c_cflag part.&lt;br /&gt;Usually you'd use the following to enable parity checking, and strip the&lt;br /&gt;parity bit off the data, before your program reads it.&lt;br /&gt;&lt;br /&gt; options.c_iflag |= (INPCK | ISTRIP);&lt;br /&gt;&lt;br /&gt;You might use IGNPAR, which ignores all parity errors. PARMRK marks parity&lt;br /&gt;errors by inserting a DEL(255) and NUL character before the bad character.&lt;br /&gt;If IGNPAR is enabled, only a NUL is inserted.&lt;br /&gt;&lt;br /&gt;You may set software flow control using&lt;br /&gt;&lt;br /&gt; options.c_iflag |= (IXON | IXOFF | IXANY);&lt;br /&gt;&lt;br /&gt;Refer to section 15 for input mode constants.&lt;br /&gt;&lt;br /&gt;9.6. POSIX output modes&lt;br /&gt;&lt;br /&gt;To set port output modes, use the c_oflag member.&lt;br /&gt;To select processed output, use the following. Of all the output modes, you&lt;br /&gt;will probably only use ONCLR to convert newlines into CR and LFs.&lt;br /&gt;&lt;br /&gt; options.c_oflag |= OPOST;&lt;br /&gt;&lt;br /&gt;For raw output, use&lt;br /&gt;&lt;br /&gt; options.c_oflag &amp;amp;= ~OPOST;&lt;br /&gt;&lt;br /&gt;Refer to section 16 for output mode constants.&lt;br /&gt;&lt;br /&gt;9.7. POSIX control modes&lt;br /&gt;&lt;br /&gt;You may set the control characters using the c_cc part.&lt;br /&gt;Set the software flow control characters in the VSTART and VSTOP&lt;br /&gt;elements. The standard is DC1(17) and DC3(19) for XON and XOFF.&lt;br /&gt;VMIN specifies the minimum number of 0 to read. If it is 0, then&lt;br /&gt;VTIME specifies the time to wait for each character.&lt;br /&gt;If VMIN is not 0, VTIME is the time to wait to read the first character.&lt;br /&gt;If the first character is read, then any read() will be blocked until all&lt;br /&gt;VMIN characters are read.&lt;br /&gt;VTIME is specified in tenths of seconds. If it is 0, then read()s will&lt;br /&gt;be permanently blocked unless NDELAY was previously specified with fcntl().&lt;br /&gt;&lt;br /&gt;Refer to section 17 for control mode constants.&lt;br /&gt;&lt;br /&gt;10. Sample program&lt;br /&gt;&lt;br /&gt;This program is a skeleton COM2 reader, which was used for our project.&lt;br /&gt;It did not need all of the information specified above for&lt;br /&gt;configuring ports. The 20ms delay is used to indicate that data coming into&lt;br /&gt;the port is buffered, and is available for the next read().&lt;br /&gt;&lt;br /&gt;/* Better port reading program&lt;br /&gt;  v1.0&lt;br /&gt;  23-10-96&lt;br /&gt; &lt;br /&gt;  This test program uses quasi-POSIX compliant UNIX functions to&lt;br /&gt;  open the ABU port and read.&lt;br /&gt; &lt;br /&gt;  Uses termio functions to initialise the port to 9600 baud, at&lt;br /&gt;  8 data bits, no parity, no hardware flow control,&lt;br /&gt;  and features character buffering.&lt;br /&gt;  The 20ms delay after the port read indicates that characters are&lt;br /&gt;  buffered if a button is pressed many times.&lt;br /&gt; &lt;br /&gt;  This program was derived from instructions at&lt;br /&gt;   http://www.easysw.com/~mike/serial/&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;#include &lt;stdio.h&gt;   /* Standard input/output definitions */&lt;br /&gt;#include &lt;string.h&gt;  /* String function definitions */&lt;br /&gt;#include &lt;unistd.h&gt;  /* UNIX standard function definitions */&lt;br /&gt;#include &lt;fcntl.h&gt;   /* File control definitions */&lt;br /&gt;#include &lt;errno.h&gt;   /* Error number definitions */&lt;br /&gt;#include &lt;termios.h&gt; /* POSIX terminal control definitions */&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * 'open_port()' - Open serial port 1.&lt;br /&gt; *&lt;br /&gt; * Returns the file descriptor on success or -1 on error.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;int open_port(void)&lt;br /&gt;{&lt;br /&gt;  int fd;                                   /* File descriptor for the port */&lt;br /&gt;&lt;br /&gt;  fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);&lt;br /&gt;&lt;br /&gt;  if (fd == -1)&lt;br /&gt;  {                                              /* Could not open the port */&lt;br /&gt;    fprintf(stderr, "open_port: Unable to open /dev/ttyS1 - %s\n",&lt;br /&gt;            strerror(errno));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return (fd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;{&lt;br /&gt;int mainfd=0;                                            /* File descriptor */&lt;br /&gt;char chout;&lt;br /&gt;struct termios options;&lt;br /&gt; &lt;br /&gt;mainfd = open_port();&lt;br /&gt;&lt;br /&gt;fcntl(mainfd, F_SETFL, FNDELAY);                  /* Configure port reading */&lt;br /&gt;                                    /* Get the current options for the port */&lt;br /&gt;tcgetattr(mainfd, &amp;amp;options);&lt;br /&gt;cfsetispeed(&amp;amp;options, B9600);                 /* Set the baud rates to 9600 */&lt;br /&gt;cfsetospeed(&amp;amp;options, B9600);&lt;br /&gt;  &lt;br /&gt;                                  /* Enable the receiver and set local mode */&lt;br /&gt;options.c_cflag |= (CLOCAL | CREAD);&lt;br /&gt;options.c_cflag &amp;amp;= ~PARENB; /* Mask the character size to 8 bits, no parity */&lt;br /&gt;options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;options.c_cflag |=  CS8;                              /* Select 8 data bits */&lt;br /&gt;options.c_cflag &amp;amp;= ~CRTSCTS;               /* Disable hardware flow control */ &lt;br /&gt;&lt;br /&gt;                                /* Enable data to be processed as raw input */&lt;br /&gt;options.c_lflag &amp;amp;= ~(ICANON | ECHO | ISIG);&lt;br /&gt;     &lt;br /&gt;                                       /* Set the new options for the port */&lt;br /&gt;tcsetattr(mainfd, TCSANOW, &amp;amp;options);&lt;br /&gt;                       &lt;br /&gt;while (1)&lt;br /&gt;{&lt;br /&gt;  read(mainfd, &amp;amp;chout, sizeof(chout));          /* Read character from ABU */&lt;br /&gt; &lt;br /&gt;  if (chout != 0)&lt;br /&gt;     printf("Got %c.\n", chout);&lt;br /&gt;&lt;br /&gt;  chout=0;&lt;br /&gt;  usleep(20000);&lt;br /&gt;}&lt;br /&gt;                                                   /* Close the serial port */&lt;br /&gt; close(mainfd);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;11. Character and parity settings&lt;br /&gt;&lt;br /&gt;   No parity (8N1):&lt;br /&gt;&lt;br /&gt;    options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;    options.c_cflag |= CS8;&lt;br /&gt;&lt;br /&gt;   Even parity (7E1):&lt;br /&gt;&lt;br /&gt;    options.c_cflag |= PARENB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~PARODD;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;    options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;   Odd parity (7O1):&lt;br /&gt;&lt;br /&gt;    options.c_cflag |= PARENB;&lt;br /&gt;    options.c_cflag |= PARODD;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;    options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;   Mark parity is simulated by using 2 stop bits (7M1):&lt;br /&gt;&lt;br /&gt;    options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;    options.c_cflag |= CSTOPB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;    options.c_cflag |= CS7;&lt;br /&gt;&lt;br /&gt;   Space parity is setup the same as no parity (7S1):&lt;br /&gt;&lt;br /&gt;    options.c_cflag &amp;amp;= ~PARENB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSTOPB;&lt;br /&gt;    options.c_cflag &amp;amp;= ~CSIZE;&lt;br /&gt;    options.c_cflag |= CS8;&lt;br /&gt;&lt;br /&gt;12. POSIX control mode flags&lt;br /&gt;&lt;br /&gt;The following table lists the possible control modes for c_cflag. &lt;br /&gt; &lt;br /&gt;  Constant     Description&lt;br /&gt;  ________________________&lt;br /&gt; &lt;br /&gt;  CBAUD        Bit mask for baud rate        &lt;br /&gt;  B0           0 baud (drop DTR)        &lt;br /&gt;  B50          50 baud        &lt;br /&gt;  B75          75 baud        &lt;br /&gt;  B110         110 baud        &lt;br /&gt;  B134         134.5 baud        &lt;br /&gt;  B150         150 baud        &lt;br /&gt;  B200         200 baud        &lt;br /&gt;  B300         300 baud        &lt;br /&gt;  B600         600 baud        &lt;br /&gt;  B1200        1200 baud        &lt;br /&gt;  B1800        1800 baud        &lt;br /&gt;  B2400        2400 baud        &lt;br /&gt;  B4800        4800 baud        &lt;br /&gt;  B9600        9600 baud        &lt;br /&gt;  B19200       19200 baud        &lt;br /&gt;  B38400       38400 baud        &lt;br /&gt;  EXTA         External rate clock        &lt;br /&gt;  EXTB         External rate clock        &lt;br /&gt;  CSIZE        Bit mask for data bits        &lt;br /&gt;  CS5          5 data bits        &lt;br /&gt;  CS6          6 data bits        &lt;br /&gt;  CS7          7 data bits        &lt;br /&gt;  CS8          8 data bits        &lt;br /&gt;  CSTOPB       2 stop bits (1 otherwise)        &lt;br /&gt;  CREAD        Enable receiver        &lt;br /&gt;  PARENB       Enable parity bit        &lt;br /&gt;  PARODD       Use odd parity instead of even        &lt;br /&gt;  HUPCL        Hangup (drop DTR) on last close        &lt;br /&gt;  CLOCAL       Local line - do not change 'owner' of port     &lt;br /&gt;  LOBLK        Block job control output        &lt;br /&gt;  CRTSCTS      Enable hardware flow control (not supported on all platforms)        &lt;br /&gt;&lt;br /&gt;13. POSIX tcsetattr Constants&lt;br /&gt;&lt;br /&gt;  Constant   Description&lt;br /&gt;  ______________________&lt;br /&gt; &lt;br /&gt;  TCSANOW    Make changes now without waiting for data to complete&lt;br /&gt;  TCSADRAIN  Wait until everything has been transmitted&lt;br /&gt;  TCSAFLUSH  Flush input and output buffers and make the change&lt;br /&gt;&lt;br /&gt;14. POSIX Local Mode Constants&lt;br /&gt;&lt;br /&gt;  Constant   Description&lt;br /&gt;  ______________________&lt;br /&gt; &lt;br /&gt;  ISIG       Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals&lt;br /&gt;  ICANON     Enable canonical input (else raw)&lt;br /&gt;  XCASE      Map uppercase \lowercase (obselete)&lt;br /&gt;  ECHO       Enable echoing of input characters&lt;br /&gt;  ECHOE      Echo erase character as BS-SP-BS&lt;br /&gt;  ECHOK      Echo NL after kill character&lt;br /&gt;  ECHONL     Echo NL&lt;br /&gt;  NOFLSH     Disable flushing of input buffers after interrupt&lt;br /&gt;             or quit characters&lt;br /&gt;  IEXTEN     Enable extended functions&lt;br /&gt;  ECHOCTL    Echo control characters as ^char and delete as ~?&lt;br /&gt;  ECHOPRT    Echo erased character as character erased&lt;br /&gt;  ECHOKE     BS-SP-BS entire line on line kill&lt;br /&gt;  FLUSHO     Output being flushed&lt;br /&gt;  PENDIN     Retype pending input at next read or input char&lt;br /&gt;  TOSTOP     Send SIGTTOU for background output&lt;br /&gt;&lt;br /&gt;15. POSIX Input Mode Constants&lt;br /&gt;&lt;br /&gt;  Constant   Description&lt;br /&gt;  ______________________&lt;br /&gt; &lt;br /&gt;  INPCK      Enable parity check&lt;br /&gt;  IGNPAR     Ignore parity errors&lt;br /&gt;  PARMRK     Mark parity errors&lt;br /&gt;  ISTRIP     Strip parity bits&lt;br /&gt;  IXON       Enable software flow control (outgoing)&lt;br /&gt;  IXOFF      Enable software flow control (incoming)&lt;br /&gt;  IXANY      Allow any character to start flow again&lt;br /&gt;  IGNBRK     Ignore break condition&lt;br /&gt;  BRKINT     Send a SIGINT when a break condition is detected&lt;br /&gt;  INLCR      Map NL to CR&lt;br /&gt;  IGNCR      Ignore CR&lt;br /&gt;  ICRNL      Map CR to NL&lt;br /&gt;  IUCLC      Map uppercase to lowercase&lt;br /&gt;  IMAXBEL    Echo BEL on input line too long&lt;br /&gt;&lt;br /&gt;16. POSIX Output Mode Constants&lt;br /&gt;&lt;br /&gt;  Constant   Description&lt;br /&gt;  ______________________&lt;br /&gt; &lt;br /&gt;  OPOST      Postprocess output (not set = raw output)&lt;br /&gt;  OLCUC      Map lowercase to uppercase&lt;br /&gt;  ONLCR      Map NL to CR-NL&lt;br /&gt;  OCRNL      Map CR to NL&lt;br /&gt;  NOCR       No CR output at column 0&lt;br /&gt;  ONLRET     NL performs CR function&lt;br /&gt;  OFILL      Use fill characters for delay&lt;br /&gt;  OFDEL      Fill character is DEL&lt;br /&gt;  NLDLY      Mask for delay time needed between lines&lt;br /&gt;  NL0        No delay for NLs&lt;br /&gt;  NL1        Delay further output after newline for 100 milliseconds&lt;br /&gt;  CRDLY      Mask for delay time needed to return carriage to left column&lt;br /&gt;  CR0        No delay for CRs&lt;br /&gt;  CR1        Delay after CRs depending on current column position&lt;br /&gt;  CR2        Delay 100 milliseconds after sending CRs&lt;br /&gt;  CR3        Delay 150 milliseconds after sending CRs&lt;br /&gt;  TABDLY     Mask for delay time needed after TABs&lt;br /&gt;  TAB0       No delay for TABs&lt;br /&gt;  TAB1       Delay after TABs depending on current column position&lt;br /&gt;  TAB2       Delay 100 milliseconds after sending TABs&lt;br /&gt;  TAB3       Expand TAB characters to spaces&lt;br /&gt;  BSDLY      Mask for delay time needed after BSs&lt;br /&gt;  BS0        No delay for BSs&lt;br /&gt;  BS1        Delay 50 milliseconds after sending BSs&lt;br /&gt;  VTDLY      Mask for delay time needed after VTs&lt;br /&gt;  VT0        No delay for VTs&lt;br /&gt;  VT1        Delay 2 seconds after sending VTs&lt;br /&gt;  FFDLY      Mask for delay time needed after FFs&lt;br /&gt;  FF0        No delay for FFs&lt;br /&gt;  FF1        Delay 2 seconds after sending FFs&lt;br /&gt;&lt;br /&gt;17. POSIX Control Character Constants&lt;br /&gt;&lt;br /&gt;  Constant   Description          Key&lt;br /&gt;  ______________________________________&lt;br /&gt; &lt;br /&gt;  VINTR      Interrupt            CTRL-C&lt;br /&gt;  VQUIT      Quit                 CTRL-Z&lt;br /&gt;  VERASE     Erase                Backspace (BS)&lt;br /&gt;  VKILL      Kill-line            CTRL-U&lt;br /&gt;  VEOF       End-of-file          CTRL-D&lt;br /&gt;  VEOL       End-of-line          Carriage return (CR)&lt;br /&gt;  VEOL2      Second end-of-line   Line feed (LF)&lt;br /&gt;  VMIN       Minimum number of characters to read&lt;br /&gt;  VTIME      Time to wait for data (tenths of seconds)&lt;br /&gt;&lt;br /&gt;----------------- End of Linux Serial Programming Mini-Howto -----------------&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-6772549873399199987?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/6772549873399199987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=6772549873399199987' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/6772549873399199987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/6772549873399199987'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/linux-serial-port-programming-mini.html' title='Linux Serial Port Programming Mini-Howto'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-1225597003066053537</id><published>2008-05-27T22:42:00.001-07:00</published><updated>2008-05-27T22:42:47.858-07:00</updated><title type='text'>More MInicom Options</title><content type='html'>Minicom is a serial communication program to access a network or security device  through its console port.&lt;br /&gt;This tool is similar to Hyper Terminal, which is by default available on a Microsoft  Windows system. &lt;br /&gt;&lt;br /&gt;Let's install Minicom:&lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;b&gt;#apt-get install minicom&lt;/b&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; Check if you have active serial ports:&lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;  &lt;b&gt;#dmesg | grep tty&lt;/b&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;i&gt;[17179573.660000] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A&lt;br /&gt;[17179573.660000] serial8250: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A &lt;/i&gt; &lt;br /&gt;&lt;br /&gt; The read and write permissions are required on the /dev/ttyS0 file.    The dialout group, which is the default group owner of the   file, has already these rights.   &lt;br /&gt; You can see it with the following command:&lt;br /&gt;&lt;br /&gt; &lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;b&gt;  #ls -la /dev | grep ttyS0 &lt;/b&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;i&gt;crw-rw----  1 root dialout   4,  64 2007-02-26 22:55 ttyS0&lt;/i&gt;&lt;br /&gt;&lt;br /&gt; If the permissions are not set as above, you can configure them as follow:&lt;br /&gt;&lt;br /&gt;  &lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;b&gt; #chown root /dev/ttyS0&lt;br /&gt;#chgrp dialout /dev/ttyS0&lt;br /&gt;#chmod 660 /dev/ttyS0&lt;/b&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;    Now we are ready to add your Debian or Ubuntu user   in the dialout group:       &lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;b&gt;#adduser &lt;i&gt;your_user&lt;/i&gt; dialout&lt;/b&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; To see which users are members of the dialout group, open the /etc/group  file and look for the line beginning with dialout. &lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;  &lt;b&gt;  #cat /etc/group | grep dialout&lt;/b&gt;  &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;  &lt;i&gt;dialout:x:20:cupsys,your_user&lt;/i&gt;    &lt;br /&gt;&lt;br /&gt; We can now start Minicom: &lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;  &lt;b&gt;#minicom -s&lt;/b&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom1.gif" alt="minicom configuration Serial port setup" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_droite.gif" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom2.gif" alt="minicom configuration change which setting" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_reverse.gif" /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;table&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom3.gif" alt="minicom configuration save setup as dfl" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_droite.gif" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom4.gif" alt="minicom configuration exit" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_droite.gif" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom5.gif" alt="minicom initializing modem" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_reverse.gif" /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;   &lt;table&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td style="border: 1px solid black;"&gt; &lt;img src="http://www.openmaniak.com/image/minicom6.gif" alt="minicom welcome" /&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;   &lt;br /&gt;To leave Minicom: Ctlr A -&gt; Z -&gt; X&lt;br /&gt;The default config will be saved as /etc/minicom/minirc.dfl&lt;br /&gt;The next time you want to use Minicom you  just have to enter the following command:&lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt; &lt;b&gt;#minicom&lt;/b&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;   To save your Minicom settings on a specific file:&lt;br /&gt;&lt;br /&gt;&lt;table class="texte_table1"&gt; &lt;tbody&gt;&lt;tr&gt;&lt;td&gt;  &lt;b&gt;#minicom -s&lt;/b&gt; &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;table&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom7.gif" alt="minicom configuration save setup as" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/arrow_droite.gif" /&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="http://www.openmaniak.com/image/minicom8.gif" alt="minicom configuration save setup as" /&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  The config will be saved as /etc/minicom/minirc.config1&lt;br /&gt;To start Minicom with settings configured on a specific file:&lt;br /&gt;&lt;br /&gt;  &lt;b&gt; #minicom -s &lt;i&gt;config1&lt;/i&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-1225597003066053537?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/1225597003066053537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=1225597003066053537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1225597003066053537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1225597003066053537'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/more-minicom-options.html' title='More MInicom Options'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-1762532228122010252</id><published>2008-05-27T01:07:00.000-07:00</published><updated>2008-05-27T01:08:20.683-07:00</updated><title type='text'>Receiving</title><content type='html'>Receiving bytes by a serial port is similar to sending them only it's in the opposite direction.  It's also interrupt driven.  For the obsolete type of serial port with 1-byte buffers, when a byte is fully received from the external cable it goes into the 1-byte receive buffer.  Then the port gives the CPU an interrupt to tell it to pick up that byte so that the serial port will have room for storing the next byte which is currently being received.  For newer serial ports with 16-byte buffers, this interrupt (to fetch the bytes) may be sent after 14 bytes are in the receive buffer.  The CPU then stops what it was doing, runs the interrupt service routine, and picks up 14 to 16 bytes from the port.  For an interrupt sent when the 14th byte has been received, there could be 16 bytes to get if 2 more bytes have arrived since the interrupt.  But if 3 more bytes should arrive (instead of 2), then the 16-byte buffer will overrun.  It also may pick up less than 14 bytes by setting it that way or due to timeouts&lt;br /&gt;&lt;br /&gt;&lt;h2&gt; FIFOs  &lt;/h2&gt;  &lt;p&gt; To understand the differences between dumb and FIFO (First In, First Out queue discipline) first let's examine what happens when a UART has sent or received a byte.  The UART itself can't do anything with the data passing thru it, it just receives and sends it.  For the obsolete dumb UARTS, the CPU gets an interrupt from the serial device every time a byte has been sent or received.  The CPU then moves the received byte out of the UART's buffer and into memory somewhere, or gives the UART another byte to send.  The obsolete 8250 and 16450 UARTs only have a 1 byte buffer.  That means, that every time 1 byte is sent or received, the CPU is interrupted.  At low transfer rates, this is OK.  But, at high transfer rates, the CPU gets so busy dealing with the UART, that is doesn't have time to adequately tend to other tasks.  In some cases, the CPU does not get around to servicing the interrupt in time, and the byte is overwritten, because they are coming in so fast.  This is called an "overrun" or "overflow".&lt;/p&gt; &lt;p&gt;FIFO UARTs help solve this problem.  The 16550A (or 16550) FIFO chip comes with 16 byte FIFO buffers.  This means that it can receive up to 14 bytes (or send 16 bytes) before it has to interrupt the CPU.  Not only can it wait for more bytes, but the CPU then can transfer all (14 to 16) bytes at a time.  This is a significant advantage over the obsolete UARTs, which only had 1 byte buffers.  The CPU receives less interrupts, and is free to do other things.  Data is rarely lost. Note that the interrupt threshold of FIFO buffers (trigger level) may be set at less than 14.  1, 4 and 8 are other possible choices.  As of late 2000 there was no way the Linux user could set these directly (setserial can't do it).  While many PC's only have a 16550 with 16-byte buffers, better UARTS have even larger buffers.&lt;/p&gt; &lt;p&gt;Note that the interrupt is issued slightly before the buffer gets full (at say a "trigger level" of 14 bytes for a 16-byte buffer).  This allows room for a couple more bytes to be received before the interrupt service routine is able to actually fetch all these bytes. The trigger level may be set to various permitted values by kernel software.  A trigger level of 1 will be almost like an obsolete UART (except that it still has room for 15 more bytes after it issues the interrupt).&lt;/p&gt; &lt;p&gt;Now consider the case where you're on the Internet.  It's just sent you a short webpage of text.  All of this came in thru the serial port.  If you had a 16-byte buffer on the serial port which held back characters until it had 14 of them, some of the last several characters on the screen might be missing as the FIFO buffer waited to get the 14th character.  But the 14th character doesn't arrive since you've been sent the entire page (over the phone line) and there are no more characters to send to you.  It could be that these last characters are part of the HTML formatting, etc. and are not characters to display on the screen but you don't want to lose format either.&lt;/p&gt; &lt;p&gt;There is a "timeout" to prevent the above problem.  The "timeout" works like this for the receive UART buffer: If characters arrive one after another, then an interrupt is issued only when say the 14th character reaches the buffer.  But if a character arrives and the next character doesn't arrive soon thereafter, then an interrupt is issued anyway.  This results in fetching all of the characters in the FIFO buffer, even if only a few (or only one) are present.  There is also "timeout" for the transmit buffer as well&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Why FIFO Buffers are Small &lt;/h2&gt;  &lt;p&gt;You may wonder why the FIFO buffers are not larger.  After all, memory is cheap and it wouldn't cost much more to use buffers in the kilo-byte range.  The reason is flow control.  Flow control stops the flow of data (bytes) on serial line when necessary.  If a stop signal is sent to serial port, then the stop request is handled by software (even if the flow control is "hardware").  The serial port hardware knows nothing about flow control.&lt;/p&gt; &lt;p&gt;If the serial port buffer contains 64 bytes ready to send when it receives a flow control signal to stop sending, it will send out the 64 bytes anyway in violation of the stop request.  There is no stopping it since it doesn't know about flow control.  If the buffer was large, then many more bytes would be sent in violation of flow control's request to stop.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-1762532228122010252?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/1762532228122010252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=1762532228122010252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1762532228122010252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/1762532228122010252'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/receiving.html' title='Receiving'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-8070154771533169017</id><published>2008-05-27T01:04:00.000-07:00</published><updated>2008-05-27T01:06:30.923-07:00</updated><title type='text'>Transmitting</title><content type='html'>&lt;p&gt; Transmitting is sending bytes out of the serial port away from the computer.  Once you understand transmitting, receiving is easy to understand since it's similar.  The first explanation given here will be grossly oversimplified.  Then more detail will be added in later explanations.  When the computer wants to send a byte out the serial port (to the external cable) the CPU sends the byte on the bus inside the computer to the I/O (Input Output) address of the serial port. I/O is often written as just IO.  The serial port takes the byte, and sends it out one bit at a time (a serial bit-stream) on the transmit pin of the serial cable connector.  For what a bit (and byte) look like electrically see  Voltage Waveshapes.&lt;/p&gt; &lt;p&gt;Here's a replay of the above in a little more detail (but still very incomplete).  Most of the work at the serial port is done by the UART chip (or the like).  To transmit a byte, the serial device driver program (running on the CPU) sends a byte to the serial port"s I/O address.  This byte gets into a 1-byte "transmit shift register" in the serial port.  From this shift register bits are taken from the byte one-by-one and sent out bit-by-bit on the serial line.  Then when the last bit has been sent and the shift register needs another byte to send it could just ask the CPU to send it another byte.  Thus would be simple but it would likely introduce delays since the CPU might not be able to get the byte immediately.  After all, the CPU is usually doing other things besides just handling the serial port.&lt;/p&gt; &lt;p&gt;A way to eliminate such delays is to arrange things so that the CPU gets the byte before the shift register needs it and stores it in a serial port buffer (in hardware).  Then when the shift register has sent out its byte and needs a new byte immediately, the serial port hardware just transfers the next byte from its own buffer to the shift register.  No need to call the CPU to fetch a new byte.&lt;/p&gt; &lt;p&gt;The size of this serial port buffer was originally only one byte, but today it is usually 16 bytes (more in higher priced serial ports). Now there is still the problem of keeping this buffer sufficiently supplied with bytes so that when the shift register needs a byte to transmit it will always find one there (unless there are no more bytes to send).  This is done by contacting the CPU using an interrupt.&lt;/p&gt; &lt;p&gt;First we'll explain the case of the old fashioned one-byte buffer, since 16-byte buffers work similarly (but are more complex).  When the shift register grabs the byte out of the buffer and the buffer needs another byte, it sends an interrupt to the CPU by putting a voltage on a dedicated wire on the computer bus.  Unless the CPU is doing something very important, the interrupt forces it to stop what it was doing and start running a program which will supply another byte to the port's buffer.  The purpose of this buffer is to keep an extra byte (waiting to be sent) queued in hardware so that there will be no gaps in the transmission of bytes out the serial port cable.&lt;/p&gt; &lt;p&gt;Once the CPU gets the interrupt, it will know who sent the interrupt since there is a dedicated interrupt wire for each serial port (unless interrupts are shared).  Then the CPU will start running the serial device driver which checks registers at I/0 addresses to find out what has happened.  It finds out that the serial's transmit buffer is empty and waiting for another byte.  So if there are more bytes to send, it sends the next byte to the serial port's I/0 address.  This next byte should arrive when the previous byte is still in the transmit shift register and is still being transmitted bit-by-bit.&lt;/p&gt; &lt;p&gt;In review, when a byte has been fully transmitted out the transmit wire of the serial port and the shift register is now empty the following 3 things happen almost simultaneously:&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;ol&gt;&lt;li&gt; The next byte is moved from the transmit buffer into the transmit shift register&lt;/li&gt;&lt;li&gt; The transmission of this new byte (bit-by-bit) begins&lt;/li&gt;&lt;li&gt; Another interrupt is issued to tell the device driver to send yet another byte to the now empty transmit buffer&lt;/li&gt;&lt;/ol&gt;  &lt;p&gt;Thus we say that the serial port is interrupt driven.  Each time the serial port issues an interrupt, the CPU sends it another byte.  Once a byte has been sent to the transmit buffer by the CPU, then the CPU is free to pursue some other activity until it gets the next interrupt.  The serial port transmits bits at a fixed rate which is selected by the user (or an application program).  It's sometimes called the baud rate.  The serial port also adds extra bits to each byte (start, stop and perhaps parity bits) so there are often 10 bits sent per byte.  At a rate (also called speed) of 19,200 bits per second (bps), there are thus 1,920 bytes/sec (and also 1,920 interrupts/sec).&lt;/p&gt; &lt;p&gt;Doing all this is a lot of work for the CPU.  This is true for many reasons.  First, just sending one 8-bit byte at a time over a 32-bit data bus (or even 64-bit) is not a very efficient use of bus width. Also, there is a lot of overhead in handing each interrupt.  When the interrupt is received, the device driver only knows that something caused an interrupt at the serial port but doesn't know that it's because a character has been sent.  The device driver has to make various checks to find out what happened.  The same interrupt could mean that a character was received, one of the control lines changed state, etc.&lt;/p&gt; &lt;p&gt;A major improvement has been the enlargement of the buffer size of the serial port from 1-byte to 16-bytes.  This means that when the CPU gets an interrupt it gives the serial port up to 16 new bytes to transmit.  This is fewer interrupts to service but data must still be transferred one byte at a time over a wide bus.  The 16-byte buffer is actually a FIFO (First In First Out) queue and is often called a FIFO. See  FIFOs for details about the FIFO along with a repeat of some of the above info.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5296319277701400211-8070154771533169017?l=serialportprogramming.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://serialportprogramming.blogspot.com/feeds/8070154771533169017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=5296319277701400211&amp;postID=8070154771533169017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8070154771533169017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5296319277701400211/posts/default/8070154771533169017'/><link rel='alternate' type='text/html' href='http://serialportprogramming.blogspot.com/2008/05/transmitting.html' title='Transmitting'/><author><name>Manoj Maurya</name><uri>http://www.blogger.com/profile/07820797331061290982</uri><email>manojlu03@gmail.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='05290608493870419394'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5296319277701400211.post-3819785626355998902</id><published>2008-05-26T23:41:00.000-07:00</published><updated>2008-05-26T23:42:38.610-07:00</updated><title type='text'>Introduction to Serial Communications</title><content type='html'>&lt;p&gt;&lt;img src="http://www.taltech.com/TALtech_web/images/r_insercom.gif" alt="Introduction to Serial Communications" border="0" height="18" width="371" /&gt;  &lt;/p&gt;&lt;p&gt;All IBM PC and compatible computers are typically equipped with two serial ports and one parallel port. Although these two types of ports are used for communicating with external devices, they work in different ways.&lt;br /&gt;&lt;br /&gt;A parallel port sends and receives data eight bits at a time over 8 separate wires. This allows data to be transferred very quickly; however, the cable required is more bulky because of the number of individual wires it must contain. Parallel ports are typically used to connect a PC to a printer and are rarely used for much else. A serial port sends and receives data one bit at a time over one wire. While it takes eight times as long to transfer each byte of data this way, only a few wires are required. In fact, two-way (full duplex) communications is possible with only three separate wires - one to send, one to receive, and a common signal ground wire.&lt;br /&gt;&lt;br /&gt;  --&lt;/p&gt;&lt;a name="bidir"&gt;&lt;/a&gt; &lt;h2&gt;Bi-Directional Communications&lt;/h2&gt; &lt;p&gt;The serial port on your PC is a full-duplex device meaning that it can send and receive data at the same time. In order to be able to do this, it uses separate lines for transmitting and receiving data. Some types of serial devices support only one-way communications and therefore use only two wires in the cable - the transmit line and the signal ground.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;  &lt;/p&gt;  &lt;a name="commbits"&gt;--&lt;/a&gt;  &lt;h2&gt;Communicating by Bits&lt;/h2&gt;&lt;p&gt; Once the start bit has been sent, the transmitter sends the actual data bits. There may either be 5, 6, 7, or 8 data bits, depending on the number you have selected. Both receiver and the transmitter must agree on the number of data bits, as well as the baud rate. Almost all devices transmit data using either 7 or 8 databits.&lt;br /&gt;&lt;br /&gt;Notice that when only 7 data bits are employed, you cannot send ASCII values greater than 127. Likewise, using 5 bits limits the highest possible value to 31. After the data has been transmitted, a stop bit is sent. A stop bit has a value of 1 - or a mark state - and it can be detected correctly even if the previous data bit also had a value of 1. This is accomplished by the stop bit's duration. Stop bits can be 1, 1.5, or 2 bit periods in length.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;a name="parity"&gt;--&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;The Parity Bit&lt;/h2&gt;    &lt;p&gt; Besides the synchronization provided by the use of start and stop bits, an additional bit called a parity bit may optionally be transmitted along with the data. A parity bit affords a small amount of error checking, to help detect data corruption that might occur during transmission. You can choose either even parity, odd parity, mark parity, space parity or none at all. When even or odd parity is being used, the number of marks (logical 1 bits) in each data byte are counted, and a single bit is transmitted following the data bits to indicate whether the number of 1 bits just sent is even or odd.&lt;br /&gt;&lt;br /&gt;For example, when even parity is chosen, the parity bit is transmitted with a value of 0 if the number of preceding marks is an even number. For the binary value of 0110 0011 the parity bit would be 0. If even parity were in effect and the binary number 1101 0110 were sent, then the parity bit would be 1. Odd parity is just the opposite, and the parity bit is 0 when the number of mark bits in the preceding word is an odd number. Parity error checking is very rudimentary. While it will tell you if there is a single bit error in the character, it doesn't show which bit was received in error. Also, if an even number of bits are in error then the parity bit would not reflect any error at all.&lt;br /&gt;&lt;br /&gt;Mark parity means that the parity bit is always set to the mark signal condition and likewise space parity always sends the parity bit in the space signal condition. Since these two parity options serve no useful purpose whatsoever, they are almost never used.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;  &lt;/p&gt;      &lt;a name="232c"&gt;--&lt;/a&gt;  &lt;h2&gt;RS-232C&lt;/h2&gt;    &lt;p&gt;RS-232 stands for Recommend Standard number 232 and C is the latest revision of the standard. The serial ports on most computers use a subset of the RS-232C standard. The full RS-232C standard specifies a 25-pin "D" connector of which 22 pins are used. Most of these pins are not needed for normal PC communications, and indeed, most new PCs are equipped with male D type connectors having only 9 pins.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;  &lt;/p&gt;    &lt;a name="dce"&gt;--&lt;/a&gt;    &lt;h2&gt;DCE and DTE Devices&lt;/h2&gt;                 &lt;p&gt;Two terms you should be familiar with are DTE and DCE. DTE stands for Data Terminal Equipment, and DCE stands for Data Communications Equipment. These terms are used to indicate the pin-out for the connectors on a device and the direction of the signals on the pins. Your computer is a DTE device, while most other devices are usually DCE devices.&lt;br /&gt;         &lt;br /&gt;If you have trouble keeping the two straight then replace the term "DTE device" with "your PC" and the term "DCE device" with "remote device" in the following discussion.&lt;br /&gt;         &lt;br /&gt;The RS-232 standard states that DTE devices use a 25-pin male connector, and DCE devices use a 25-pin female connector. You can therefore connect a DTE device to a DCE using a straight pin-for-pin connection. However, to connect two like devices, you must instead use a null modem cable. Null modem cables cross the transmit and receive lines in the cable, and are discussed later in this chapter. The listing below shows the connections and signal directions for both 25 and 9-pin connectors.&lt;br /&gt;          &lt;/p&gt;                 &lt;table border="1" cellpadding="2" cellspacing="0" width="100%"&gt;               &lt;tbody&gt;&lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;&lt;br /&gt;&lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;&lt;b&gt;25 Pin Connector on a DTE device (PC connection)&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;Male RS232 DB25&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;&lt;img alt="25 pin to 9 pin connector" src="http://www.taltech.com/TALtech_web/images/25p.gif" border="0" height="48" width="287" /&gt; &lt;/td&gt;               &lt;/tr&gt;               &lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;&lt;b&gt;Pin Number&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;&lt;b&gt;Direction of signal:&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;1&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Protective Ground &lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;2&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Transmitted Data (TD) Outgoing Data (from a DTE to a DCE)&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;3&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Received Data (RD) Incoming Data (from a DCE to a DTE)&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;4&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Request To Send (RTS) Outgoing flow control signal controlled                      by DTE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;5&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Clear To Send (CTS) Incoming flow control signal controlled                      by DCE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;6&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Data Set Ready (DSR) Incoming handshaking signal controlled                      by DCE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;7&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Signal Ground Common reference voltage&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;8&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Carrier Detect (CD) Incoming signal from a modem&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;20&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Data Terminal Ready (DTR) Outgoing handshaking signal controlled                      by DTE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;22&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Ring Indicator (RI) Incoming signal from a modem &lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;             &lt;/tbody&gt;&lt;/table&gt;          &lt;br /&gt;                       &lt;table border="1" cellpadding="2" cellspacing="0" width="100%"&gt;               &lt;tbody&gt;&lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;&lt;br /&gt;&lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;&lt;b&gt;9 Pin Connector on a DTE device (PC connection)&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;Male RS232 DB9 &lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;&lt;img alt="9 pin D connector" src="http://www.taltech.com/TALtech_web/images/9d.gif" height="48" width="150" /&gt;                  &lt;/td&gt;               &lt;/tr&gt;               &lt;tr align="center" bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;&lt;b&gt;Pin Number&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;&lt;b&gt;Direction of signal:&lt;/b&gt;&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;1&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Carrier Detect (CD) (from DCE) Incoming signal from a modem&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;2&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Received Data (RD) Incoming Data from a DCE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;3&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Transmitted Data (TD) Outgoing Data to a DCE&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;4&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Data Terminal Ready (DTR) Outgoing handshaking signal &lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;5&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Signal Ground Common reference voltage&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;6&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Data Set Ready (DSR) Incoming handshaking signal&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;7&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Request To Send (RTS) Outgoing flow control signal&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="White"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;8&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Clear To Send (CTS) Incoming flow control signal&lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;               &lt;tr bgcolor="#efefe7"&gt;                  &lt;td width="16%"&gt;                    &lt;p&gt;9&lt;/p&gt;                 &lt;/td&gt;                 &lt;td width="84%"&gt;                    &lt;p&gt;Ring Indicator (RI) (from DCE) Incoming signal from a modem                    &lt;/p&gt;                 &lt;/td&gt;               &lt;/tr&gt;             &lt;/tbody&gt;&lt;/table&gt;             &lt;p&gt; The TD (transmit data) wire is the one through which data from a DTE device is transmitted to a DCE device. This name can be deceiving, because this wire is used by a DCE device to receive its data. The TD line is kept in a mark condition by the DTE device when it is idle. The RD (receive data) wire is the one on which data is received by a DTE device, and the DCE device keeps this line in a mark condition when idle.&lt;br /&gt;         &lt;br /&gt;            &lt;b&gt;RTS&lt;/b&gt; stands for &lt;b&gt;Request To Send&lt;/b&gt;. This line and the CTS line are used when "hardware flow control" is enabled in both the DTE and DCE devices. The DTE device puts this line in a mark condition to tell the remote device that it is ready and able to receive data. If the DTE device is not able to receive data (typically because its receive buffer is almost full), it will put this line in the space condition as a signal to the DCE to stop sending data. When the DTE device is ready to receive more data (i.e. after data has been removed from its receive buffer), it will place this line back in the mark condition. The complement of the RTS wire is CTS, which stands for Clear To Send. The DCE device puts this line in a mark condition to tell the DTE device that it is ready to receive the data. Likewise, if the DCE device is unable to receive data, it will place this line in the space condition. Together, these two lines make up what is called RTS/CTS or "hardware" flow control. The Software Wedge supports this type of flow control, as well as Xon/XOff or "software" flow control. Software flow control uses special control characters transmitted from one device to another to tell the other device to stop or start sending data. With software flow control the RTS and CTS lines are not used.&lt;br /&gt;         &lt;br /&gt;            &lt;b&gt;DTR&lt;/b&gt; stands for &lt;b&gt;Data Terminal Ready&lt;/b&gt;. Its intended function is very similar to the RTS line. DSR (Data Set Ready) is the companion to DTR in the same way that CTS is to RTS. Some serial devices use DTR and DSR as signals to simply confirm that a device is connected and is turned on. The Software Wedge sets DTR to the mark state when the serial port is opened and leaves it in that state until the port is closed. The DTR and DSR lines were originally designed to provide an alternate method of hardware handshaking. It would be pointless to use both RTS/CTS and DTR/DSR for flow control signals at the same time. Because of this, DTR and DSR are rarely used for flow control.&lt;br /&gt;         &lt;br /&gt;            &lt;b&gt;CD&lt;/b&gt; stands for &lt;b&gt;Carrier Detect&lt;/b&gt;. Carrier Detect is used by a modem to signal that it has a made a connection with another modem, or has detected a carrier tone.&lt;br /&gt;         &lt;br /&gt;            The last remaining line is &lt;b&gt;RI&lt;/b&gt; or &lt;b&gt;Ring Indicator&lt;/b&gt;. A                modem toggles the state of this line when an incoming call rings                your phone.&lt;br /&gt;         &lt;br /&gt;The Carrier Detect (CD) and the Ring Indicator (RI) lines are only available in connections to a modem. Because most modems transmit status information to a PC when either a carrier signal is detected (i.e. when a connection is made to another modem) or when the line is ringing, these two lines are rarely used.&lt;br /&gt;            &lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt; &lt;/p&gt;             &lt;a name="9to5"&gt;--&lt;/a&gt;             &lt;h2&gt;9 to 25 Pin Adapters&lt;/h2&gt;    &lt;p&gt;The     following table shows the connections inside a standard 9 pin to 25 pin adapter.&lt;/p&gt;       &lt;table border="1" cellpadding="0" cellspacing="0" width="50%"&gt;       &lt;tbody&gt;&lt;tr&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;&lt;b&gt;9-Pin Connector&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;&lt;b&gt;25 Pin Connector&lt;/b&gt;&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 1 DCD&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 8 DCD&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 2 RD&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 3 RD&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 3 TD&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 2 TD&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 4 DTR&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 20 DTR&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 5 GND&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 7 GND&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 6 DSR&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 6 DSR&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 7 RTS&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 4 RTS&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 8 CTS&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" width="50%"&gt;&lt;p&gt;Pin 5 CTS&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;       &lt;tr&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 9 RI&lt;/p&gt;&lt;/td&gt;         &lt;td align="left" bgcolor="#efefe7" width="50%"&gt;&lt;p&gt;Pin 22 RI&lt;/p&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;  &lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/p&gt;   &lt;a name="baud"&gt;--&lt;/a&gt;  &lt;h2&gt;Baud vs. Bits per Second&lt;/h2&gt;     &lt;p&gt;The baud unit is named after Jean Maurice Emile Baudot, who was an officer in the French Telegraph Service. He is credited with devising the first uniform-length 5-bit code for characters of the alphabet in the late 19th century. What baud really refers to is modulation rate or the number of times per second that a line changes state. This is not always the same as bits per second (BPS). If you connect two serial devices together using direct cables then baud and BPS are in fact the same. Thus, if you are running at 19200 BPS, then the line is also changing states 19200 times per second. But when considering modems, this isn't the case.&lt;br /&gt;&lt;br /&gt;Because modems transfer signals over a telephone line, the baud rate is actually limited to a maximum of 2400 baud. This is a physical restriction of the lines provided by the phone company. The increased data throughput achieved with 9600 or higher baud modems is accomplished by using sophisticated phase modulation, and data compression techniques.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;  &lt;/p&gt;        &lt;a name="cablenulls"&gt;--&lt;/a&gt;     &lt;h2&gt;Cables, Null Modems, and Gender Changers&lt;/h2&gt;     &lt;p&gt;In a perfect world, all serial ports on every computer would be DTE devices with 25-pin male "D" connectors. All other devices would be DCE devices with 25-pin female connectors. This would allow you to use a cable in which each pin on one end of the cable is connected to the same pin on the other end. Unfortunately, we don't live in a perfect world. Serial ports use both 9 and 25 pins, many devices can be configured as either DTE or DCE, and - as in the case of many data collection devices - may use completely non-standard or proprietary pin-outs. Because of this lack of standardization, special cables called null modem cables, gender changers and custom made cables are often required.&lt;br /&gt;&lt;a href="http://www.taltech.com/TALtech_web/resources/intro-sc.html#top"&gt;&lt;br /&gt;&lt;/a&gt;  &lt;/p&gt;      &lt;a name="length"&gt;--&lt;/a&gt;  &lt;h2&gt;Cables Lengths&lt;/h2&gt;     &lt;p&gt;The RS-232C standard imposes a cable length limit of 50 feet