Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / media / usb / dvb-usb / dibusb-common.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Common methods for dibusb-based-receivers.
3  *
4  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
5  *
6  * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
7  */
8
9 #include "dibusb.h"
10
11 /* Max transfer size done by I2C transfer functions */
12 #define MAX_XFER_SIZE  64
13
14 static int debug;
15 module_param(debug, int, 0644);
16 MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
17 MODULE_LICENSE("GPL");
18
19 #define deb_info(args...) dprintk(debug,0x01,args)
20
21 /* common stuff used by the different dibusb modules */
22 int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
23 {
24         if (adap->priv != NULL) {
25                 struct dibusb_state *st = adap->priv;
26                 if (st->ops.fifo_ctrl != NULL)
27                         if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
28                                 err("error while controlling the fifo of the demod.");
29                                 return -ENODEV;
30                         }
31         }
32         return 0;
33 }
34 EXPORT_SYMBOL(dibusb_streaming_ctrl);
35
36 int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
37 {
38         if (adap->priv != NULL) {
39                 struct dibusb_state *st = adap->priv;
40                 if (st->ops.pid_ctrl != NULL)
41                         st->ops.pid_ctrl(adap->fe_adap[0].fe,
42                                          index, pid, onoff);
43         }
44         return 0;
45 }
46 EXPORT_SYMBOL(dibusb_pid_filter);
47
48 int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
49 {
50         if (adap->priv != NULL) {
51                 struct dibusb_state *st = adap->priv;
52                 if (st->ops.pid_parse != NULL)
53                         if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
54                                 err("could not handle pid_parser");
55         }
56         return 0;
57 }
58 EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
59
60 int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
61 {
62         u8 *b;
63         int ret;
64
65         b = kmalloc(3, GFP_KERNEL);
66         if (!b)
67                 return -ENOMEM;
68
69         b[0] = DIBUSB_REQ_SET_IOCTL;
70         b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
71         b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
72
73         ret = dvb_usb_generic_write(d, b, 3);
74
75         kfree(b);
76
77         msleep(10);
78
79         return ret;
80 }
81 EXPORT_SYMBOL(dibusb_power_ctrl);
82
83 int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
84 {
85         int ret;
86         u8 *b;
87
88         b = kmalloc(3, GFP_KERNEL);
89         if (!b)
90                 return -ENOMEM;
91
92         if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
93                 goto ret;
94
95         if (onoff) {
96                 b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
97                 b[1] = 0x00;
98                 ret = dvb_usb_generic_write(adap->dev, b, 2);
99                 if (ret  < 0)
100                         goto ret;
101         }
102
103         b[0] = DIBUSB_REQ_SET_IOCTL;
104         b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
105         ret = dvb_usb_generic_write(adap->dev, b, 3);
106
107 ret:
108         kfree(b);
109         return ret;
110 }
111 EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
112
113 int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
114 {
115         u8 *b;
116         int ret;
117
118         if (!onoff)
119                 return 0;
120
121         b = kmalloc(3, GFP_KERNEL);
122         if (!b)
123                 return -ENOMEM;
124
125         b[0] = DIBUSB_REQ_SET_IOCTL;
126         b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
127         b[2] = DIBUSB_IOCTL_POWER_WAKEUP;
128
129         ret = dvb_usb_generic_write(d, b, 3);
130
131         kfree(b);
132
133         return ret;
134 }
135 EXPORT_SYMBOL(dibusb2_0_power_ctrl);
136
137 static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
138                           u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
139 {
140         u8 *sndbuf;
141         int ret, wo, len;
142
143         /* write only ? */
144         wo = (rbuf == NULL || rlen == 0);
145
146         len = 2 + wlen + (wo ? 0 : 2);
147
148         sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL);
149         if (!sndbuf)
150                 return -ENOMEM;
151
152         if (4 + wlen > MAX_XFER_SIZE) {
153                 warn("i2c wr: len=%d is too big!\n", wlen);
154                 ret = -EOPNOTSUPP;
155                 goto ret;
156         }
157
158         sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
159         sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
160
161         memcpy(&sndbuf[2], wbuf, wlen);
162
163         if (!wo) {
164                 sndbuf[wlen + 2] = (rlen >> 8) & 0xff;
165                 sndbuf[wlen + 3] = rlen & 0xff;
166         }
167
168         ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0);
169
170 ret:
171         kfree(sndbuf);
172         return ret;
173 }
174
175 /*
176  * I2C master xfer function
177  */
178 static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
179 {
180         struct dvb_usb_device *d = i2c_get_adapdata(adap);
181         int i;
182
183         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
184                 return -EAGAIN;
185
186         for (i = 0; i < num; i++) {
187                 /* write/read request */
188                 if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0
189                                           && (msg[i+1].flags & I2C_M_RD)) {
190                         if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
191                                                 msg[i+1].buf,msg[i+1].len) < 0)
192                                 break;
193                         i++;
194                 } else if ((msg[i].flags & I2C_M_RD) == 0) {
195                         if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
196                                 break;
197                 } else if (msg[i].addr != 0x50) {
198                         /* 0x50 is the address of the eeprom - we need to protect it
199                          * from dibusb's bad i2c implementation: reads without
200                          * writing the offset before are forbidden */
201                         if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0)
202                                 break;
203                 }
204         }
205
206         mutex_unlock(&d->i2c_mutex);
207         return i;
208 }
209
210 static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
211 {
212         return I2C_FUNC_I2C;
213 }
214
215 struct i2c_algorithm dibusb_i2c_algo = {
216         .master_xfer   = dibusb_i2c_xfer,
217         .functionality = dibusb_i2c_func,
218 };
219 EXPORT_SYMBOL(dibusb_i2c_algo);
220
221 int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
222 {
223         u8 *buf;
224         int rc;
225
226         buf = kmalloc(2, GFP_KERNEL);
227         if (!buf)
228                 return -ENOMEM;
229
230         buf[0] = offs;
231
232         rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1);
233         *val = buf[1];
234         kfree(buf);
235
236         return rc;
237 }
238 EXPORT_SYMBOL(dibusb_read_eeprom_byte);
239
240 /*
241  * common remote control stuff
242  */
243 struct rc_map_table rc_map_dibusb_table[] = {
244         /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
245         { 0x0016, KEY_POWER },
246         { 0x0010, KEY_MUTE },
247         { 0x0003, KEY_1 },
248         { 0x0001, KEY_2 },
249         { 0x0006, KEY_3 },
250         { 0x0009, KEY_4 },
251         { 0x001d, KEY_5 },
252         { 0x001f, KEY_6 },
253         { 0x000d, KEY_7 },
254         { 0x0019, KEY_8 },
255         { 0x001b, KEY_9 },
256         { 0x0015, KEY_0 },
257         { 0x0005, KEY_CHANNELUP },
258         { 0x0002, KEY_CHANNELDOWN },
259         { 0x001e, KEY_VOLUMEUP },
260         { 0x000a, KEY_VOLUMEDOWN },
261         { 0x0011, KEY_RECORD },
262         { 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
263         { 0x0014, KEY_PLAY },
264         { 0x001a, KEY_STOP },
265         { 0x0040, KEY_REWIND },
266         { 0x0012, KEY_FASTFORWARD },
267         { 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
268         { 0x004c, KEY_PAUSE },
269         { 0x004d, KEY_SCREEN }, /* Full screen mode. */
270         { 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
271         /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
272         { 0x000c, KEY_CANCEL }, /* Cancel */
273         { 0x001c, KEY_EPG }, /* EPG */
274         { 0x0000, KEY_TAB }, /* Tab */
275         { 0x0048, KEY_INFO }, /* Preview */
276         { 0x0004, KEY_LIST }, /* RecordList */
277         { 0x000f, KEY_TEXT }, /* Teletext */
278         /* Key codes for the KWorld/ADSTech/JetWay remote. */
279         { 0x8612, KEY_POWER },
280         { 0x860f, KEY_SELECT }, /* source */
281         { 0x860c, KEY_UNKNOWN }, /* scan */
282         { 0x860b, KEY_EPG },
283         { 0x8610, KEY_MUTE },
284         { 0x8601, KEY_1 },
285         { 0x8602, KEY_2 },
286         { 0x8603, KEY_3 },
287         { 0x8604, KEY_4 },
288         { 0x8605, KEY_5 },
289         { 0x8606, KEY_6 },
290         { 0x8607, KEY_7 },
291         { 0x8608, KEY_8 },
292         { 0x8609, KEY_9 },
293         { 0x860a, KEY_0 },
294         { 0x8618, KEY_ZOOM },
295         { 0x861c, KEY_UNKNOWN }, /* preview */
296         { 0x8613, KEY_UNKNOWN }, /* snap */
297         { 0x8600, KEY_UNDO },
298         { 0x861d, KEY_RECORD },
299         { 0x860d, KEY_STOP },
300         { 0x860e, KEY_PAUSE },
301         { 0x8616, KEY_PLAY },
302         { 0x8611, KEY_BACK },
303         { 0x8619, KEY_FORWARD },
304         { 0x8614, KEY_UNKNOWN }, /* pip */
305         { 0x8615, KEY_ESC },
306         { 0x861a, KEY_UP },
307         { 0x861e, KEY_DOWN },
308         { 0x861f, KEY_LEFT },
309         { 0x861b, KEY_RIGHT },
310
311         /* Key codes for the DiBcom MOD3000 remote. */
312         { 0x8000, KEY_MUTE },
313         { 0x8001, KEY_TEXT },
314         { 0x8002, KEY_HOME },
315         { 0x8003, KEY_POWER },
316
317         { 0x8004, KEY_RED },
318         { 0x8005, KEY_GREEN },
319         { 0x8006, KEY_YELLOW },
320         { 0x8007, KEY_BLUE },
321
322         { 0x8008, KEY_DVD },
323         { 0x8009, KEY_AUDIO },
324         { 0x800a, KEY_IMAGES },      /* Pictures */
325         { 0x800b, KEY_VIDEO },
326
327         { 0x800c, KEY_BACK },
328         { 0x800d, KEY_UP },
329         { 0x800e, KEY_RADIO },
330         { 0x800f, KEY_EPG },
331
332         { 0x8010, KEY_LEFT },
333         { 0x8011, KEY_OK },
334         { 0x8012, KEY_RIGHT },
335         { 0x8013, KEY_UNKNOWN },    /* SAP */
336
337         { 0x8014, KEY_TV },
338         { 0x8015, KEY_DOWN },
339         { 0x8016, KEY_MENU },       /* DVD Menu */
340         { 0x8017, KEY_LAST },
341
342         { 0x8018, KEY_RECORD },
343         { 0x8019, KEY_STOP },
344         { 0x801a, KEY_PAUSE },
345         { 0x801b, KEY_PLAY },
346
347         { 0x801c, KEY_PREVIOUS },
348         { 0x801d, KEY_REWIND },
349         { 0x801e, KEY_FASTFORWARD },
350         { 0x801f, KEY_NEXT},
351
352         { 0x8040, KEY_1 },
353         { 0x8041, KEY_2 },
354         { 0x8042, KEY_3 },
355         { 0x8043, KEY_CHANNELUP },
356
357         { 0x8044, KEY_4 },
358         { 0x8045, KEY_5 },
359         { 0x8046, KEY_6 },
360         { 0x8047, KEY_CHANNELDOWN },
361
362         { 0x8048, KEY_7 },
363         { 0x8049, KEY_8 },
364         { 0x804a, KEY_9 },
365         { 0x804b, KEY_VOLUMEUP },
366
367         { 0x804c, KEY_CLEAR },
368         { 0x804d, KEY_0 },
369         { 0x804e, KEY_ENTER },
370         { 0x804f, KEY_VOLUMEDOWN },
371 };
372 EXPORT_SYMBOL(rc_map_dibusb_table);
373
374 int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
375 {
376         u8 *buf;
377         int ret;
378
379         buf = kmalloc(5, GFP_KERNEL);
380         if (!buf)
381                 return -ENOMEM;
382
383         buf[0] = DIBUSB_REQ_POLL_REMOTE;
384
385         ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0);
386         if (ret < 0)
387                 goto ret;
388
389         dvb_usb_nec_rc_key_to_event(d, buf, event, state);
390
391         if (buf[0] != 0)
392                 deb_info("key: %*ph\n", 5, buf);
393
394 ret:
395         kfree(buf);
396
397         return ret;
398 }
399 EXPORT_SYMBOL(dibusb_rc_query);