Annotation of tme/generic/serial.c, revision 1.1.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.