linux/drivers/media/usb/as102/as10x_cmd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Abilis Systems Single DVB-T Receiver
   4 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
   5 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
   6 */
   7
   8#include <linux/kernel.h>
   9#include "as102_drv.h"
  10#include "as10x_cmd.h"
  11
  12/**
  13 * as10x_cmd_turn_on - send turn on command to AS10x
  14 * @adap:   pointer to AS10x bus adapter
  15 *
  16 * Return 0 when no error, < 0 in case of error.
  17 */
  18int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
  19{
  20        int error = AS10X_CMD_ERROR;
  21        struct as10x_cmd_t *pcmd, *prsp;
  22
  23        pcmd = adap->cmd;
  24        prsp = adap->rsp;
  25
  26        /* prepare command */
  27        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  28                        sizeof(pcmd->body.turn_on.req));
  29
  30        /* fill command */
  31        pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
  32
  33        /* send command */
  34        if (adap->ops->xfer_cmd) {
  35                error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
  36                                            sizeof(pcmd->body.turn_on.req) +
  37                                            HEADER_SIZE,
  38                                            (uint8_t *) prsp,
  39                                            sizeof(prsp->body.turn_on.rsp) +
  40                                            HEADER_SIZE);
  41        }
  42
  43        if (error < 0)
  44                goto out;
  45
  46        /* parse response */
  47        error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
  48
  49out:
  50        return error;
  51}
  52
  53/**
  54 * as10x_cmd_turn_off - send turn off command to AS10x
  55 * @adap:   pointer to AS10x bus adapter
  56 *
  57 * Return 0 on success or negative value in case of error.
  58 */
  59int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
  60{
  61        int error = AS10X_CMD_ERROR;
  62        struct as10x_cmd_t *pcmd, *prsp;
  63
  64        pcmd = adap->cmd;
  65        prsp = adap->rsp;
  66
  67        /* prepare command */
  68        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  69                        sizeof(pcmd->body.turn_off.req));
  70
  71        /* fill command */
  72        pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
  73
  74        /* send command */
  75        if (adap->ops->xfer_cmd) {
  76                error = adap->ops->xfer_cmd(
  77                        adap, (uint8_t *) pcmd,
  78                        sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
  79                        (uint8_t *) prsp,
  80                        sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
  81        }
  82
  83        if (error < 0)
  84                goto out;
  85
  86        /* parse response */
  87        error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
  88
  89out:
  90        return error;
  91}
  92
  93/**
  94 * as10x_cmd_set_tune - send set tune command to AS10x
  95 * @adap:    pointer to AS10x bus adapter
  96 * @ptune:   tune parameters
  97 *
  98 * Return 0 on success or negative value in case of error.
  99 */
 100int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
 101                       struct as10x_tune_args *ptune)
 102{
 103        int error = AS10X_CMD_ERROR;
 104        struct as10x_cmd_t *preq, *prsp;
 105
 106        preq = adap->cmd;
 107        prsp = adap->rsp;
 108
 109        /* prepare command */
 110        as10x_cmd_build(preq, (++adap->cmd_xid),
 111                        sizeof(preq->body.set_tune.req));
 112
 113        /* fill command */
 114        preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
 115        preq->body.set_tune.req.args.freq = (__force __u32)cpu_to_le32(ptune->freq);
 116        preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
 117        preq->body.set_tune.req.args.hier_select = ptune->hier_select;
 118        preq->body.set_tune.req.args.modulation = ptune->modulation;
 119        preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
 120        preq->body.set_tune.req.args.interleaving_mode  =
 121                ptune->interleaving_mode;
 122        preq->body.set_tune.req.args.code_rate  = ptune->code_rate;
 123        preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
 124        preq->body.set_tune.req.args.transmission_mode  =
 125                ptune->transmission_mode;
 126
 127        /* send command */
 128        if (adap->ops->xfer_cmd) {
 129                error = adap->ops->xfer_cmd(adap,
 130                                            (uint8_t *) preq,
 131                                            sizeof(preq->body.set_tune.req)
 132                                            + HEADER_SIZE,
 133                                            (uint8_t *) prsp,
 134                                            sizeof(prsp->body.set_tune.rsp)
 135                                            + HEADER_SIZE);
 136        }
 137
 138        if (error < 0)
 139                goto out;
 140
 141        /* parse response */
 142        error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
 143
 144out:
 145        return error;
 146}
 147
 148/**
 149 * as10x_cmd_get_tune_status - send get tune status command to AS10x
 150 * @adap: pointer to AS10x bus adapter
 151 * @pstatus: pointer to updated status structure of the current tune
 152 *
 153 * Return 0 on success or negative value in case of error.
 154 */
 155int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
 156                              struct as10x_tune_status *pstatus)
 157{
 158        int error = AS10X_CMD_ERROR;
 159        struct as10x_cmd_t  *preq, *prsp;
 160
 161        preq = adap->cmd;
 162        prsp = adap->rsp;
 163
 164        /* prepare command */
 165        as10x_cmd_build(preq, (++adap->cmd_xid),
 166                        sizeof(preq->body.get_tune_status.req));
 167
 168        /* fill command */
 169        preq->body.get_tune_status.req.proc_id =
 170                cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
 171
 172        /* send command */
 173        if (adap->ops->xfer_cmd) {
 174                error = adap->ops->xfer_cmd(
 175                        adap,
 176                        (uint8_t *) preq,
 177                        sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
 178                        (uint8_t *) prsp,
 179                        sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
 180        }
 181
 182        if (error < 0)
 183                goto out;
 184
 185        /* parse response */
 186        error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
 187        if (error < 0)
 188                goto out;
 189
 190        /* Response OK -> get response data */
 191        pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
 192        pstatus->signal_strength  =
 193                le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.signal_strength);
 194        pstatus->PER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.PER);
 195        pstatus->BER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.BER);
 196
 197out:
 198        return error;
 199}
 200
 201/**
 202 * as10x_cmd_get_tps - send get TPS command to AS10x
 203 * @adap:      pointer to AS10x handle
 204 * @ptps:      pointer to TPS parameters structure
 205 *
 206 * Return 0 on success or negative value in case of error.
 207 */
 208int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
 209{
 210        int error = AS10X_CMD_ERROR;
 211        struct as10x_cmd_t *pcmd, *prsp;
 212
 213        pcmd = adap->cmd;
 214        prsp = adap->rsp;
 215
 216        /* prepare command */
 217        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 218                        sizeof(pcmd->body.get_tps.req));
 219
 220        /* fill command */
 221        pcmd->body.get_tune_status.req.proc_id =
 222                cpu_to_le16(CONTROL_PROC_GETTPS);
 223
 224        /* send command */
 225        if (adap->ops->xfer_cmd) {
 226                error = adap->ops->xfer_cmd(adap,
 227                                            (uint8_t *) pcmd,
 228                                            sizeof(pcmd->body.get_tps.req) +
 229                                            HEADER_SIZE,
 230                                            (uint8_t *) prsp,
 231                                            sizeof(prsp->body.get_tps.rsp) +
 232                                            HEADER_SIZE);
 233        }
 234
 235        if (error < 0)
 236                goto out;
 237
 238        /* parse response */
 239        error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
 240        if (error < 0)
 241                goto out;
 242
 243        /* Response OK -> get response data */
 244        ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
 245        ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
 246        ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
 247        ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
 248        ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
 249        ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
 250        ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;
 251        ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
 252        ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
 253        ptps->cell_ID = le16_to_cpu((__force __le16)prsp->body.get_tps.rsp.tps.cell_ID);
 254
 255out:
 256        return error;
 257}
 258
 259/**
 260 * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
 261 * @adap:          pointer to AS10x bus adapter
 262 * @pdemod_stats:  pointer to demod stats parameters structure
 263 *
 264 * Return 0 on success or negative value in case of error.
 265 */
 266int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
 267                              struct as10x_demod_stats *pdemod_stats)
 268{
 269        int error = AS10X_CMD_ERROR;
 270        struct as10x_cmd_t *pcmd, *prsp;
 271
 272        pcmd = adap->cmd;
 273        prsp = adap->rsp;
 274
 275        /* prepare command */
 276        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 277                        sizeof(pcmd->body.get_demod_stats.req));
 278
 279        /* fill command */
 280        pcmd->body.get_demod_stats.req.proc_id =
 281                cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
 282
 283        /* send command */
 284        if (adap->ops->xfer_cmd) {
 285                error = adap->ops->xfer_cmd(adap,
 286                                (uint8_t *) pcmd,
 287                                sizeof(pcmd->body.get_demod_stats.req)
 288                                + HEADER_SIZE,
 289                                (uint8_t *) prsp,
 290                                sizeof(prsp->body.get_demod_stats.rsp)
 291                                + HEADER_SIZE);
 292        }
 293
 294        if (error < 0)
 295                goto out;
 296
 297        /* parse response */
 298        error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
 299        if (error < 0)
 300                goto out;
 301
 302        /* Response OK -> get response data */
 303        pdemod_stats->frame_count =
 304                le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.frame_count);
 305        pdemod_stats->bad_frame_count =
 306                le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
 307        pdemod_stats->bytes_fixed_by_rs =
 308                le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
 309        pdemod_stats->mer =
 310                le16_to_cpu((__force __le16)prsp->body.get_demod_stats.rsp.stats.mer);
 311        pdemod_stats->has_started =
 312                prsp->body.get_demod_stats.rsp.stats.has_started;
 313
 314out:
 315        return error;
 316}
 317
 318/**
 319 * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
 320 * @adap:     pointer to AS10x bus adapter
 321 * @is_ready: pointer to value indicating when impulse
 322 *            response data is ready
 323 *
 324 * Return 0 on success or negative value in case of error.
 325 */
 326int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
 327                               uint8_t *is_ready)
 328{
 329        int error = AS10X_CMD_ERROR;
 330        struct as10x_cmd_t *pcmd, *prsp;
 331
 332        pcmd = adap->cmd;
 333        prsp = adap->rsp;
 334
 335        /* prepare command */
 336        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 337                        sizeof(pcmd->body.get_impulse_rsp.req));
 338
 339        /* fill command */
 340        pcmd->body.get_impulse_rsp.req.proc_id =
 341                cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
 342
 343        /* send command */
 344        if (adap->ops->xfer_cmd) {
 345                error = adap->ops->xfer_cmd(adap,
 346                                        (uint8_t *) pcmd,
 347                                        sizeof(pcmd->body.get_impulse_rsp.req)
 348                                        + HEADER_SIZE,
 349                                        (uint8_t *) prsp,
 350                                        sizeof(prsp->body.get_impulse_rsp.rsp)
 351                                        + HEADER_SIZE);
 352        }
 353
 354        if (error < 0)
 355                goto out;
 356
 357        /* parse response */
 358        error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
 359        if (error < 0)
 360                goto out;
 361
 362        /* Response OK -> get response data */
 363        *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
 364
 365out:
 366        return error;
 367}
 368
 369/**
 370 * as10x_cmd_build - build AS10x command header
 371 * @pcmd:     pointer to AS10x command buffer
 372 * @xid:      sequence id of the command
 373 * @cmd_len:  length of the command
 374 */
 375void as10x_cmd_build(struct as10x_cmd_t *pcmd,
 376                     uint16_t xid, uint16_t cmd_len)
 377{
 378        pcmd->header.req_id = cpu_to_le16(xid);
 379        pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
 380        pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
 381        pcmd->header.data_len = cpu_to_le16(cmd_len);
 382}
 383
 384/**
 385 * as10x_rsp_parse - Parse command response
 386 * @prsp:       pointer to AS10x command buffer
 387 * @proc_id:    id of the command
 388 *
 389 * Return 0 on success or negative value in case of error.
 390 */
 391int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
 392{
 393        int error;
 394
 395        /* extract command error code */
 396        error = prsp->body.common.rsp.error;
 397
 398        if ((error == 0) &&
 399            (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
 400                return 0;
 401        }
 402
 403        return AS10X_CMD_ERROR;
 404}
 405