Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: Zlib
  2
  3#include "../zlib_inflate/inflate.h"
  4#include "dfltcc_util.h"
  5#include "dfltcc_inflate.h"
  6#include <asm/setup.h>
  7#include <linux/export.h>
  8#include <linux/zutil.h>
  9
 10/*
 11 * Expand.
 12 */
 13int dfltcc_can_inflate(
 14    z_streamp strm
 15)
 16{
 17    struct inflate_state *state = (struct inflate_state *)strm->state;
 18    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 19
 20    /* Check for kernel dfltcc command line parameter */
 21    if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
 22            zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)
 23        return 0;
 24
 25    /* Unsupported hardware */
 26    return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
 27               is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
 28}
 29EXPORT_SYMBOL(dfltcc_can_inflate);
 30
 31void dfltcc_reset_inflate_state(z_streamp strm) {
 32    struct inflate_state *state = (struct inflate_state *)strm->state;
 33    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 34
 35    dfltcc_reset_state(dfltcc_state);
 36}
 37EXPORT_SYMBOL(dfltcc_reset_inflate_state);
 38
 39static int dfltcc_was_inflate_used(
 40    z_streamp strm
 41)
 42{
 43    struct inflate_state *state = (struct inflate_state *)strm->state;
 44    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 45
 46    return !param->nt;
 47}
 48
 49static int dfltcc_inflate_disable(
 50    z_streamp strm
 51)
 52{
 53    struct inflate_state *state = (struct inflate_state *)strm->state;
 54    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 55
 56    if (!dfltcc_can_inflate(strm))
 57        return 0;
 58    if (dfltcc_was_inflate_used(strm))
 59        /* DFLTCC has already decompressed some data. Since there is not
 60         * enough information to resume decompression in software, the call
 61         * must fail.
 62         */
 63        return 1;
 64    /* DFLTCC was not used yet - decompress in software */
 65    memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
 66    return 0;
 67}
 68
 69static dfltcc_cc dfltcc_xpnd(
 70    z_streamp strm
 71)
 72{
 73    struct inflate_state *state = (struct inflate_state *)strm->state;
 74    struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
 75    size_t avail_in = strm->avail_in;
 76    size_t avail_out = strm->avail_out;
 77    dfltcc_cc cc;
 78
 79    cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
 80                param, &strm->next_out, &avail_out,
 81                &strm->next_in, &avail_in, state->window);
 82    strm->avail_in = avail_in;
 83    strm->avail_out = avail_out;
 84    return cc;
 85}
 86
 87dfltcc_inflate_action dfltcc_inflate(
 88    z_streamp strm,
 89    int flush,
 90    int *ret
 91)
 92{
 93    struct inflate_state *state = (struct inflate_state *)strm->state;
 94    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
 95    struct dfltcc_param_v0 *param = &dfltcc_state->param;
 96    dfltcc_cc cc;
 97
 98    if (flush == Z_BLOCK || flush == Z_PACKET_FLUSH) {
 99        /* DFLTCC does not support stopping on block boundaries (Z_BLOCK flush option)
100         * as well as the use of Z_PACKET_FLUSH option (used exclusively by PPP driver)
101         */
102        if (dfltcc_inflate_disable(strm)) {
103            *ret = Z_STREAM_ERROR;
104            return DFLTCC_INFLATE_BREAK;
105        } else
106            return DFLTCC_INFLATE_SOFTWARE;
107    }
108
109    if (state->last) {
110        if (state->bits != 0) {
111            strm->next_in++;
112            strm->avail_in--;
113            state->bits = 0;
114        }
115        state->mode = CHECK;
116        return DFLTCC_INFLATE_CONTINUE;
117    }
118
119    if (strm->avail_in == 0 && !param->cf)
120        return DFLTCC_INFLATE_BREAK;
121
122    if (!state->window || state->wsize == 0) {
123        state->mode = MEM;
124        return DFLTCC_INFLATE_CONTINUE;
125    }
126
127    /* Translate stream to parameter block */
128    param->cvt = CVT_ADLER32;
129    param->sbb = state->bits;
130    if (param->hl)
131        param->nt = 0; /* Honor history for the first block */
132    param->cv = state->check;
133
134    /* Inflate */
135    do {
136        cc = dfltcc_xpnd(strm);
137    } while (cc == DFLTCC_CC_AGAIN);
138
139    /* Translate parameter block to stream */
140    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
141    state->last = cc == DFLTCC_CC_OK;
142    state->bits = param->sbb;
143    state->check = param->cv;
144    if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
145        /* Report an error if stream is corrupted */
146        state->mode = BAD;
147        return DFLTCC_INFLATE_CONTINUE;
148    }
149    state->mode = TYPEDO;
150    /* Break if operands are exhausted, otherwise continue looping */
151    return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
152        DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
153}
154EXPORT_SYMBOL(dfltcc_inflate);