Annotation of tme/generic/serial.c, revision 1.1

1.1     ! root        1: /* $Id: serial.c,v 1.4 2003/05/05 23:14:34 fredette Exp $ */
        !             2: 
        !             3: /* generic/serial.c - generic serial implementation support: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2003 Matt Fredette
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Matt Fredette.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: 
        !            36: #include <tme/common.h>
        !            37: _TME_RCSID("$Id: serial.c,v 1.4 2003/05/05 23:14:34 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/generic/serial.h>
        !            41: 
        !            42: /* this initializes a serial buffer: */
        !            43: int
        !            44: tme_serial_buffer_init(struct tme_serial_buffer *buffer, unsigned int size)
        !            45: {
        !            46: 
        !            47:   /* round the buffer size up to a power of two: */
        !            48:   if (size & (size - 1)) {
        !            49:     do {
        !            50:       size &= (size - 1);
        !            51:     } while (size & (size - 1));
        !            52:     size <<= 1;
        !            53:   }
        !            54: 
        !            55:   /* set the buffer size: */
        !            56:   buffer->tme_serial_buffer_size = size;
        !            57: 
        !            58:   /* set the head and tail pointers: */
        !            59:   buffer->tme_serial_buffer_head = 0;
        !            60:   buffer->tme_serial_buffer_tail = 0;
        !            61: 
        !            62:   /* allocate the buffer data and flags: */
        !            63:   buffer->tme_serial_buffer_data =
        !            64:     tme_new(tme_uint8_t, size);
        !            65:   buffer->tme_serial_buffer_data_flags =
        !            66:     tme_new(tme_serial_data_flags_t, size);
        !            67: 
        !            68:   /* done: */
        !            69:   return (TME_OK);
        !            70: }
        !            71: 
        !            72: /* this copies data into a serial buffer: */
        !            73: unsigned int
        !            74: tme_serial_buffer_copyin(struct tme_serial_buffer *buffer,
        !            75:                         const tme_uint8_t *data,
        !            76:                         unsigned int count,
        !            77:                         tme_serial_data_flags_t data_flags,
        !            78:                         int copy_flags)
        !            79: {
        !            80:   unsigned int resid;
        !            81:   unsigned int buffer_head, buffer_tail, buffer_size_mask;
        !            82:   unsigned int buffer_size;
        !            83: 
        !            84:   /* get the head, tail, and size mask: */
        !            85:   buffer_head = buffer->tme_serial_buffer_head;
        !            86:   buffer_tail = buffer->tme_serial_buffer_tail;
        !            87:   buffer_size_mask = buffer->tme_serial_buffer_size - 1;
        !            88: 
        !            89:   /* while we have more data to copy in: */
        !            90:   for (resid = count; resid > 0; ) {
        !            91:     
        !            92:     /* if the buffer is full: */
        !            93:     if (((buffer_head + 1) & buffer_size_mask)
        !            94:        == buffer_tail) {
        !            95:       
        !            96:       /* if a full buffer means an overrun, mark it: */
        !            97:       if (copy_flags & TME_SERIAL_COPY_FULL_IS_OVERRUN) {
        !            98:        buffer->tme_serial_buffer_data_flags[buffer_head] |= TME_SERIAL_DATA_OVERRUN;
        !            99:       }
        !           100: 
        !           101:       /* we're done copying in: */
        !           102:       break;
        !           103:     }
        !           104: 
        !           105:     /* otherwise, the buffer is not full, meaning there is always some
        !           106:        space starting at the buffer head.  if the buffer head >= the
        !           107:        buffer tail, there is space from the buffer head up to the end
        !           108:        of the buffer, otherwise there is space from the buffer head up
        !           109:        to one before the buffer tail: */
        !           110:     buffer_size = ((buffer_head >= buffer_tail)
        !           111:                   ? (buffer_size_mask - buffer_head) + 1
        !           112:                   : (buffer_tail - buffer_head) - 1);
        !           113: 
        !           114:     /* don't copy in more data than is available: */
        !           115:     buffer_size = TME_MIN(buffer_size, resid);
        !           116:     assert(buffer_size > 0);
        !           117: 
        !           118:     /* copy in this data: */
        !           119:     memcpy(buffer->tme_serial_buffer_data + buffer_head,
        !           120:           data,
        !           121:           buffer_size);
        !           122:     memset(buffer->tme_serial_buffer_data_flags + buffer_head,
        !           123:           data_flags,
        !           124:           buffer_size);
        !           125: 
        !           126:     /* update and loop: */
        !           127:     buffer_head = (buffer_head + buffer_size) & buffer_size_mask;
        !           128:     data += buffer_size; 
        !           129:     resid -= buffer_size;
        !           130:   }
        !           131: 
        !           132:   /* store our new head pointer: */
        !           133:   buffer->tme_serial_buffer_head = buffer_head;
        !           134: 
        !           135:   /* done: */
        !           136:   return (count - resid);
        !           137: }
        !           138: 
        !           139: /* this copies data out of a buffer: */
        !           140: unsigned int
        !           141: tme_serial_buffer_copyout(struct tme_serial_buffer *buffer,
        !           142:                          tme_uint8_t *data,
        !           143:                          unsigned int count,
        !           144:                          tme_serial_data_flags_t *_data_flags,
        !           145:                          int copy_flags)
        !           146: {
        !           147:   unsigned int resid;
        !           148:   unsigned int buffer_head, buffer_tail, buffer_size_mask;
        !           149:   unsigned int buffer_size;
        !           150:   tme_serial_data_flags_t data_flags, *scan_flags;
        !           151:   unsigned int scan_resid;
        !           152: 
        !           153:   /* get the head, tail, and size mask: */
        !           154:   buffer_head = buffer->tme_serial_buffer_head;
        !           155:   buffer_tail = buffer->tme_serial_buffer_tail;
        !           156:   buffer_size_mask = buffer->tme_serial_buffer_size - 1;
        !           157: 
        !           158:   /* we can only return data with the same data flags: */
        !           159:   data_flags = buffer->tme_serial_buffer_data_flags[buffer_tail];
        !           160: 
        !           161:   /* while we have more data to copy out: */
        !           162:   for (resid = count; resid > 0; ) {
        !           163:     
        !           164:     /* if the buffer is empty: */
        !           165:     if (buffer_tail == buffer_head) {
        !           166: 
        !           167:       /* we're done copying out: */
        !           168:       break;
        !           169:     }
        !           170: 
        !           171:     /* otherwise, the buffer is not empty, meaning there is always some
        !           172:        data starting at the buffer tail.  if the buffer tail > the
        !           173:        buffer head, there is space from the buffer tail up to the end
        !           174:        of the buffer, otherwise there is space from the buffer tail up
        !           175:        to the buffer head: */
        !           176:     buffer_size = ((buffer_tail > buffer_head)
        !           177:                   ? (buffer_size_mask - buffer_tail) + 1
        !           178:                   : (buffer_head - buffer_tail));
        !           179: 
        !           180:     /* don't copy out more data than there is space available: */
        !           181:     buffer_size = TME_MIN(buffer_size, resid);
        !           182:     assert(buffer_size > 0);
        !           183: 
        !           184:     /* only copy out data with the same buffer flags.  if we just
        !           185:        wrapped in the buffer, we may find that no new data has the
        !           186:        same buffer flags as data we already copied out: */
        !           187:     scan_flags = buffer->tme_serial_buffer_data_flags + buffer_tail;
        !           188:     scan_resid = buffer_size;
        !           189:     for (; (*(scan_flags++) == data_flags
        !           190:            && --scan_resid > 0); );
        !           191:     buffer_size -= scan_resid;
        !           192:     if (buffer_size == 0) {
        !           193:       break;
        !           194:     }
        !           195: 
        !           196:     /* copy out this data: */
        !           197:     if (data != NULL) {
        !           198:       memcpy(data,
        !           199:             buffer->tme_serial_buffer_data + buffer_tail,
        !           200:             buffer_size);
        !           201:       data += buffer_size; 
        !           202:     }
        !           203: 
        !           204:     /* update and loop: */
        !           205:     buffer_tail = (buffer_tail + buffer_size) & buffer_size_mask;
        !           206:     resid -= buffer_size;
        !           207:   }
        !           208: 
        !           209:   /* store our new tail pointer: */
        !           210:   if (!(copy_flags & TME_SERIAL_COPY_PEEK)) {
        !           211:     buffer->tme_serial_buffer_tail = buffer_tail;
        !           212:   }
        !           213: 
        !           214:   /* done: */
        !           215:   if (_data_flags != NULL) {
        !           216:     *_data_flags = data_flags;
        !           217:   }
        !           218:   return (count - resid);
        !           219: }
        !           220: 
        !           221: /* this returns the amount of busy space in the buffer: */
        !           222: unsigned int
        !           223: tme_serial_buffer_space_busy(const struct tme_serial_buffer *buffer)
        !           224: {
        !           225:   unsigned int buffer_head, buffer_tail, buffer_size;
        !           226: 
        !           227:   /* get the head, tail, and size: */
        !           228:   buffer_head = buffer->tme_serial_buffer_head;
        !           229:   buffer_tail = buffer->tme_serial_buffer_tail;
        !           230:   buffer_size = buffer->tme_serial_buffer_size;
        !           231: 
        !           232:   if (buffer_head >= buffer_tail) {
        !           233:     return (buffer_head - buffer_tail);
        !           234:   }
        !           235:   else {
        !           236:     return (buffer_size - (buffer_tail - buffer_head));
        !           237:   }
        !           238: }
        !           239: 
        !           240: /* this returns the amount of free space in the buffer: */
        !           241: unsigned int
        !           242: tme_serial_buffer_space_free(const struct tme_serial_buffer *buffer)
        !           243: {
        !           244:   /* you can't completely fill the buffer: */
        !           245:   return ((buffer->tme_serial_buffer_size - 1)
        !           246:          - tme_serial_buffer_space_busy(buffer));
        !           247: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.