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