cfq-iosched: fix use-after-free of cfqq
[deliverable/linux.git] / drivers / staging / media / as102 / as10x_cmd.c
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <linux/kernel.h>
22 #include "as102_drv.h"
23 #include "as10x_types.h"
24 #include "as10x_cmd.h"
25
26 /**
27 * as10x_cmd_turn_on - send turn on command to AS10x
28 * @phandle: pointer to AS10x handle
29 *
30 * Return 0 when no error, < 0 in case of error.
31 */
32 int as10x_cmd_turn_on(as10x_handle_t *phandle)
33 {
34 int error;
35 struct as10x_cmd_t *pcmd, *prsp;
36
37 ENTER();
38
39 pcmd = phandle->cmd;
40 prsp = phandle->rsp;
41
42 /* prepare command */
43 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
44 sizeof(pcmd->body.turn_on.req));
45
46 /* fill command */
47 pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
48
49 /* send command */
50 if (phandle->ops->xfer_cmd) {
51 error = phandle->ops->xfer_cmd(phandle, (uint8_t *) pcmd,
52 sizeof(pcmd->body.turn_on.req) +
53 HEADER_SIZE,
54 (uint8_t *) prsp,
55 sizeof(prsp->body.turn_on.rsp) +
56 HEADER_SIZE);
57 } else {
58 error = AS10X_CMD_ERROR;
59 }
60
61 if (error < 0)
62 goto out;
63
64 /* parse response */
65 error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
66
67 out:
68 LEAVE();
69 return error;
70 }
71
72 /**
73 * as10x_cmd_turn_off - send turn off command to AS10x
74 * @phandle: pointer to AS10x handle
75 *
76 * Return 0 on success or negative value in case of error.
77 */
78 int as10x_cmd_turn_off(as10x_handle_t *phandle)
79 {
80 int error;
81 struct as10x_cmd_t *pcmd, *prsp;
82
83 ENTER();
84
85 pcmd = phandle->cmd;
86 prsp = phandle->rsp;
87
88 /* prepare command */
89 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
90 sizeof(pcmd->body.turn_off.req));
91
92 /* fill command */
93 pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
94
95 /* send command */
96 if (phandle->ops->xfer_cmd) {
97 error = phandle->ops->xfer_cmd(
98 phandle, (uint8_t *) pcmd,
99 sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
100 (uint8_t *) prsp,
101 sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
102 } else {
103 error = AS10X_CMD_ERROR;
104 }
105
106 if (error < 0)
107 goto out;
108
109 /* parse response */
110 error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
111
112 out:
113 LEAVE();
114 return error;
115 }
116
117 /**
118 * as10x_cmd_set_tune - send set tune command to AS10x
119 * @phandle: pointer to AS10x handle
120 * @ptune: tune parameters
121 *
122 * Return 0 on success or negative value in case of error.
123 */
124 int as10x_cmd_set_tune(as10x_handle_t *phandle, struct as10x_tune_args *ptune)
125 {
126 int error;
127 struct as10x_cmd_t *preq, *prsp;
128
129 ENTER();
130
131 preq = phandle->cmd;
132 prsp = phandle->rsp;
133
134 /* prepare command */
135 as10x_cmd_build(preq, (++phandle->cmd_xid),
136 sizeof(preq->body.set_tune.req));
137
138 /* fill command */
139 preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
140 preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
141 preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
142 preq->body.set_tune.req.args.hier_select = ptune->hier_select;
143 preq->body.set_tune.req.args.constellation = ptune->constellation;
144 preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
145 preq->body.set_tune.req.args.interleaving_mode =
146 ptune->interleaving_mode;
147 preq->body.set_tune.req.args.code_rate = ptune->code_rate;
148 preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
149 preq->body.set_tune.req.args.transmission_mode =
150 ptune->transmission_mode;
151
152 /* send command */
153 if (phandle->ops->xfer_cmd) {
154 error = phandle->ops->xfer_cmd(phandle,
155 (uint8_t *) preq,
156 sizeof(preq->body.set_tune.req)
157 + HEADER_SIZE,
158 (uint8_t *) prsp,
159 sizeof(prsp->body.set_tune.rsp)
160 + HEADER_SIZE);
161 } else {
162 error = AS10X_CMD_ERROR;
163 }
164
165 if (error < 0)
166 goto out;
167
168 /* parse response */
169 error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
170
171 out:
172 LEAVE();
173 return error;
174 }
175
176 /**
177 * as10x_cmd_get_tune_status - send get tune status command to AS10x
178 * @phandle: pointer to AS10x handle
179 * @pstatus: pointer to updated status structure of the current tune
180 *
181 * Return 0 on success or negative value in case of error.
182 */
183 int as10x_cmd_get_tune_status(as10x_handle_t *phandle,
184 struct as10x_tune_status *pstatus)
185 {
186 int error;
187 struct as10x_cmd_t *preq, *prsp;
188
189 ENTER();
190
191 preq = phandle->cmd;
192 prsp = phandle->rsp;
193
194 /* prepare command */
195 as10x_cmd_build(preq, (++phandle->cmd_xid),
196 sizeof(preq->body.get_tune_status.req));
197
198 /* fill command */
199 preq->body.get_tune_status.req.proc_id =
200 cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
201
202 /* send command */
203 if (phandle->ops->xfer_cmd) {
204 error = phandle->ops->xfer_cmd(
205 phandle,
206 (uint8_t *) preq,
207 sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
208 (uint8_t *) prsp,
209 sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
210 } else {
211 error = AS10X_CMD_ERROR;
212 }
213
214 if (error < 0)
215 goto out;
216
217 /* parse response */
218 error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
219 if (error < 0)
220 goto out;
221
222 /* Response OK -> get response data */
223 pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
224 pstatus->signal_strength =
225 le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength);
226 pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER);
227 pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER);
228
229 out:
230 LEAVE();
231 return error;
232 }
233
234 /**
235 * send get TPS command to AS10x
236 * @phandle: pointer to AS10x handle
237 * @ptps: pointer to TPS parameters structure
238 *
239 * Return 0 on success or negative value in case of error.
240 */
241 int as10x_cmd_get_tps(as10x_handle_t *phandle, struct as10x_tps *ptps)
242 {
243 int error;
244 struct as10x_cmd_t *pcmd, *prsp;
245
246 ENTER();
247
248 pcmd = phandle->cmd;
249 prsp = phandle->rsp;
250
251 /* prepare command */
252 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
253 sizeof(pcmd->body.get_tps.req));
254
255 /* fill command */
256 pcmd->body.get_tune_status.req.proc_id =
257 cpu_to_le16(CONTROL_PROC_GETTPS);
258
259 /* send command */
260 if (phandle->ops->xfer_cmd) {
261 error = phandle->ops->xfer_cmd(phandle,
262 (uint8_t *) pcmd,
263 sizeof(pcmd->body.get_tps.req) +
264 HEADER_SIZE,
265 (uint8_t *) prsp,
266 sizeof(prsp->body.get_tps.rsp) +
267 HEADER_SIZE);
268 } else {
269 error = AS10X_CMD_ERROR;
270 }
271
272 if (error < 0)
273 goto out;
274
275 /* parse response */
276 error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
277 if (error < 0)
278 goto out;
279
280 /* Response OK -> get response data */
281 ptps->constellation = prsp->body.get_tps.rsp.tps.constellation;
282 ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
283 ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
284 ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
285 ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
286 ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
287 ptps->transmission_mode = prsp->body.get_tps.rsp.tps.transmission_mode;
288 ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
289 ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
290 ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID);
291
292 out:
293 LEAVE();
294 return error;
295 }
296
297 /**
298 * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
299 * @phandle: pointer to AS10x handle
300 * @pdemod_stats: pointer to demod stats parameters structure
301 *
302 * Return 0 on success or negative value in case of error.
303 */
304 int as10x_cmd_get_demod_stats(as10x_handle_t *phandle,
305 struct as10x_demod_stats *pdemod_stats)
306 {
307 int error;
308 struct as10x_cmd_t *pcmd, *prsp;
309
310 ENTER();
311
312 pcmd = phandle->cmd;
313 prsp = phandle->rsp;
314
315 /* prepare command */
316 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
317 sizeof(pcmd->body.get_demod_stats.req));
318
319 /* fill command */
320 pcmd->body.get_demod_stats.req.proc_id =
321 cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
322
323 /* send command */
324 if (phandle->ops->xfer_cmd) {
325 error = phandle->ops->xfer_cmd(phandle,
326 (uint8_t *) pcmd,
327 sizeof(pcmd->body.get_demod_stats.req)
328 + HEADER_SIZE,
329 (uint8_t *) prsp,
330 sizeof(prsp->body.get_demod_stats.rsp)
331 + HEADER_SIZE);
332 } else {
333 error = AS10X_CMD_ERROR;
334 }
335
336 if (error < 0)
337 goto out;
338
339 /* parse response */
340 error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
341 if (error < 0)
342 goto out;
343
344 /* Response OK -> get response data */
345 pdemod_stats->frame_count =
346 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count);
347 pdemod_stats->bad_frame_count =
348 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
349 pdemod_stats->bytes_fixed_by_rs =
350 le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
351 pdemod_stats->mer =
352 le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer);
353 pdemod_stats->has_started =
354 prsp->body.get_demod_stats.rsp.stats.has_started;
355
356 out:
357 LEAVE();
358 return error;
359 }
360
361 /**
362 * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
363 * @phandle: pointer to AS10x handle
364 * @is_ready: pointer to value indicating when impulse
365 * response data is ready
366 *
367 * Return 0 on success or negative value in case of error.
368 */
369 int as10x_cmd_get_impulse_resp(as10x_handle_t *phandle,
370 uint8_t *is_ready)
371 {
372 int error;
373 struct as10x_cmd_t *pcmd, *prsp;
374
375 ENTER();
376
377 pcmd = phandle->cmd;
378 prsp = phandle->rsp;
379
380 /* prepare command */
381 as10x_cmd_build(pcmd, (++phandle->cmd_xid),
382 sizeof(pcmd->body.get_impulse_rsp.req));
383
384 /* fill command */
385 pcmd->body.get_impulse_rsp.req.proc_id =
386 cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
387
388 /* send command */
389 if (phandle->ops->xfer_cmd) {
390 error = phandle->ops->xfer_cmd(phandle,
391 (uint8_t *) pcmd,
392 sizeof(pcmd->body.get_impulse_rsp.req)
393 + HEADER_SIZE,
394 (uint8_t *) prsp,
395 sizeof(prsp->body.get_impulse_rsp.rsp)
396 + HEADER_SIZE);
397 } else {
398 error = AS10X_CMD_ERROR;
399 }
400
401 if (error < 0)
402 goto out;
403
404 /* parse response */
405 error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
406 if (error < 0)
407 goto out;
408
409 /* Response OK -> get response data */
410 *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
411
412 out:
413 LEAVE();
414 return error;
415 }
416
417 /**
418 * as10x_cmd_build - build AS10x command header
419 * @pcmd: pointer to AS10x command buffer
420 * @xid: sequence id of the command
421 * @cmd_len: length of the command
422 */
423 void as10x_cmd_build(struct as10x_cmd_t *pcmd,
424 uint16_t xid, uint16_t cmd_len)
425 {
426 pcmd->header.req_id = cpu_to_le16(xid);
427 pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
428 pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
429 pcmd->header.data_len = cpu_to_le16(cmd_len);
430 }
431
432 /**
433 * as10x_rsp_parse - Parse command response
434 * @prsp: pointer to AS10x command buffer
435 * @proc_id: id of the command
436 *
437 * Return 0 on success or negative value in case of error.
438 */
439 int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
440 {
441 int error;
442
443 /* extract command error code */
444 error = prsp->body.common.rsp.error;
445
446 if ((error == 0) &&
447 (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
448 return 0;
449 }
450
451 return AS10X_CMD_ERROR;
452 }
This page took 0.0511 seconds and 5 git commands to generate.