.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* DVB USB compliant linux driver for |
---|
2 | 3 | * |
---|
3 | 4 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 |
---|
.. | .. |
---|
21 | 22 | * |
---|
22 | 23 | * LME2510C + M88RS2000 |
---|
23 | 24 | * |
---|
24 | | - * For firmware see Documentation/media/dvb-drivers/lmedm04.rst |
---|
| 25 | + * For firmware see Documentation/admin-guide/media/lmedm04.rst |
---|
25 | 26 | * |
---|
26 | 27 | * I2C addresses: |
---|
27 | 28 | * 0xd0 - STV0288 - Demodulator |
---|
.. | .. |
---|
33 | 34 | * 0xd0 - STV0299 - Demodulator |
---|
34 | 35 | * 0xc0 - IX2410 - Tuner |
---|
35 | 36 | * |
---|
36 | | - * |
---|
37 | 37 | * VID = 3344 PID LME2510=1122 LME2510C=1120 |
---|
38 | 38 | * |
---|
39 | 39 | * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com) |
---|
40 | 40 | * LME2510(C)(C) Leaguerme (Shenzhen) MicroElectronics Co., Ltd. |
---|
41 | 41 | * |
---|
42 | | - * This program is free software; you can redistribute it and/or modify |
---|
43 | | - * it under the terms of the GNU General Public License Version 2, as |
---|
44 | | - * published by the Free Software Foundation. |
---|
45 | | - * |
---|
46 | | - * This program is distributed in the hope that it will be useful, |
---|
47 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
48 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
49 | | - * GNU General Public License for more details. |
---|
50 | | - * |
---|
51 | | - * |
---|
52 | | - * see Documentation/media/dvb-drivers/dvb-usb.rst for more information |
---|
| 42 | + * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information |
---|
53 | 43 | * |
---|
54 | 44 | * Known Issues : |
---|
55 | 45 | * LME2510: Non Intel USB chipsets fail to maintain High Speed on |
---|
.. | .. |
---|
134 | 124 | u8 stream_on; |
---|
135 | 125 | u8 pid_size; |
---|
136 | 126 | u8 pid_off; |
---|
137 | | - void *buffer; |
---|
| 127 | + u8 int_buffer[128]; |
---|
138 | 128 | struct urb *lme_urb; |
---|
139 | | - void *usb_buffer; |
---|
| 129 | + u8 usb_buffer[64]; |
---|
140 | 130 | /* Frontend original calls */ |
---|
141 | 131 | int (*fe_read_status)(struct dvb_frontend *, enum fe_status *); |
---|
142 | 132 | int (*fe_read_signal_strength)(struct dvb_frontend *, u16 *); |
---|
.. | .. |
---|
147 | 137 | u8 dvb_usb_lme2510_firmware; |
---|
148 | 138 | }; |
---|
149 | 139 | |
---|
150 | | -static int lme2510_bulk_write(struct usb_device *dev, |
---|
151 | | - u8 *snd, int len, u8 pipe) |
---|
152 | | -{ |
---|
153 | | - int actual_l; |
---|
154 | | - |
---|
155 | | - return usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), |
---|
156 | | - snd, len, &actual_l, 100); |
---|
157 | | -} |
---|
158 | | - |
---|
159 | | -static int lme2510_bulk_read(struct usb_device *dev, |
---|
160 | | - u8 *rev, int len, u8 pipe) |
---|
161 | | -{ |
---|
162 | | - int actual_l; |
---|
163 | | - |
---|
164 | | - return usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe), |
---|
165 | | - rev, len, &actual_l, 200); |
---|
166 | | -} |
---|
167 | | - |
---|
168 | 140 | static int lme2510_usb_talk(struct dvb_usb_device *d, |
---|
169 | | - u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
---|
| 141 | + u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
---|
170 | 142 | { |
---|
171 | 143 | struct lme2510_state *st = d->priv; |
---|
172 | | - u8 *buff; |
---|
173 | 144 | int ret = 0; |
---|
174 | 145 | |
---|
175 | | - if (st->usb_buffer == NULL) { |
---|
176 | | - st->usb_buffer = kmalloc(64, GFP_KERNEL); |
---|
177 | | - if (st->usb_buffer == NULL) { |
---|
178 | | - info("MEM Error no memory"); |
---|
179 | | - return -ENOMEM; |
---|
180 | | - } |
---|
181 | | - } |
---|
182 | | - buff = st->usb_buffer; |
---|
| 146 | + if (max(wlen, rlen) > sizeof(st->usb_buffer)) |
---|
| 147 | + return -EINVAL; |
---|
183 | 148 | |
---|
184 | 149 | ret = mutex_lock_interruptible(&d->usb_mutex); |
---|
185 | | - |
---|
186 | 150 | if (ret < 0) |
---|
187 | 151 | return -EAGAIN; |
---|
188 | 152 | |
---|
189 | | - /* the read/write capped at 64 */ |
---|
190 | | - memcpy(buff, wbuf, (wlen < 64) ? wlen : 64); |
---|
| 153 | + memcpy(st->usb_buffer, wbuf, wlen); |
---|
191 | 154 | |
---|
192 | | - ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); |
---|
| 155 | + ret = dvb_usbv2_generic_rw_locked(d, st->usb_buffer, wlen, |
---|
| 156 | + st->usb_buffer, rlen); |
---|
193 | 157 | |
---|
194 | | - ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ? |
---|
195 | | - rlen : 64 , 0x01); |
---|
196 | | - |
---|
197 | | - if (rlen > 0) |
---|
198 | | - memcpy(rbuf, buff, rlen); |
---|
| 158 | + if (rlen) |
---|
| 159 | + memcpy(rbuf, st->usb_buffer, rlen); |
---|
199 | 160 | |
---|
200 | 161 | mutex_unlock(&d->usb_mutex); |
---|
201 | 162 | |
---|
202 | | - return (ret < 0) ? -ENODEV : 0; |
---|
| 163 | + return ret; |
---|
203 | 164 | } |
---|
204 | 165 | |
---|
205 | 166 | static int lme2510_stream_restart(struct dvb_usb_device *d) |
---|
.. | .. |
---|
337 | 298 | |
---|
338 | 299 | switch (ibuf[0]) { |
---|
339 | 300 | case 0xaa: |
---|
340 | | - debug_data_snipet(1, "INT Remote data snipet", ibuf); |
---|
| 301 | + debug_data_snipet(1, "INT Remote data snippet", ibuf); |
---|
341 | 302 | if (!adap_to_d(adap)->rc_dev) |
---|
342 | 303 | break; |
---|
343 | 304 | |
---|
.. | .. |
---|
387 | 348 | |
---|
388 | 349 | lme2510_update_stats(adap); |
---|
389 | 350 | |
---|
390 | | - debug_data_snipet(5, "INT Remote data snipet in", ibuf); |
---|
| 351 | + debug_data_snipet(5, "INT Remote data snippet in", ibuf); |
---|
391 | 352 | break; |
---|
392 | 353 | case 0xcc: |
---|
393 | | - debug_data_snipet(1, "INT Control data snipet", ibuf); |
---|
| 354 | + debug_data_snipet(1, "INT Control data snippet", ibuf); |
---|
394 | 355 | break; |
---|
395 | 356 | default: |
---|
396 | | - debug_data_snipet(1, "INT Unknown data snipet", ibuf); |
---|
| 357 | + debug_data_snipet(1, "INT Unknown data snippet", ibuf); |
---|
397 | 358 | break; |
---|
398 | 359 | } |
---|
399 | 360 | } |
---|
.. | .. |
---|
417 | 378 | if (lme_int->lme_urb == NULL) |
---|
418 | 379 | return -ENOMEM; |
---|
419 | 380 | |
---|
420 | | - lme_int->buffer = usb_alloc_coherent(d->udev, 128, GFP_ATOMIC, |
---|
421 | | - &lme_int->lme_urb->transfer_dma); |
---|
422 | | - |
---|
423 | | - if (lme_int->buffer == NULL) |
---|
424 | | - return -ENOMEM; |
---|
425 | | - |
---|
426 | 381 | usb_fill_int_urb(lme_int->lme_urb, |
---|
427 | | - d->udev, |
---|
428 | | - usb_rcvintpipe(d->udev, 0xa), |
---|
429 | | - lme_int->buffer, |
---|
430 | | - 128, |
---|
431 | | - lme2510_int_response, |
---|
432 | | - adap, |
---|
433 | | - 8); |
---|
| 382 | + d->udev, |
---|
| 383 | + usb_rcvintpipe(d->udev, 0xa), |
---|
| 384 | + lme_int->int_buffer, |
---|
| 385 | + sizeof(lme_int->int_buffer), |
---|
| 386 | + lme2510_int_response, |
---|
| 387 | + adap, |
---|
| 388 | + 8); |
---|
434 | 389 | |
---|
435 | 390 | /* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */ |
---|
436 | 391 | ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe); |
---|
437 | 392 | |
---|
438 | 393 | if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) |
---|
439 | 394 | lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa); |
---|
440 | | - |
---|
441 | | - lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
---|
442 | 395 | |
---|
443 | 396 | usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); |
---|
444 | 397 | info("INT Interrupt Service Started"); |
---|
.. | .. |
---|
533 | 486 | static u8 obuf[64], ibuf[64]; |
---|
534 | 487 | int i, read, read_o; |
---|
535 | 488 | u16 len; |
---|
536 | | - u8 gate = st->i2c_gate; |
---|
| 489 | + u8 gate; |
---|
537 | 490 | |
---|
538 | 491 | mutex_lock(&d->i2c_mutex); |
---|
539 | | - |
---|
540 | | - if (gate == 0) |
---|
541 | | - gate = 5; |
---|
542 | 492 | |
---|
543 | 493 | for (i = 0; i < num; i++) { |
---|
544 | 494 | read_o = msg[i].flags & I2C_M_RD; |
---|
.. | .. |
---|
737 | 687 | cold = 0; |
---|
738 | 688 | break; |
---|
739 | 689 | } |
---|
740 | | - /* fall through */ |
---|
| 690 | + fallthrough; |
---|
741 | 691 | case TUNER_LG: |
---|
742 | 692 | fw_lme = fw_lg; |
---|
743 | 693 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
---|
.. | .. |
---|
760 | 710 | cold = 0; |
---|
761 | 711 | break; |
---|
762 | 712 | } |
---|
763 | | - /* fall through */ |
---|
| 713 | + fallthrough; |
---|
764 | 714 | case TUNER_LG: |
---|
765 | 715 | fw_lme = fw_c_lg; |
---|
766 | 716 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
---|
.. | .. |
---|
768 | 718 | st->dvb_usb_lme2510_firmware = TUNER_LG; |
---|
769 | 719 | break; |
---|
770 | 720 | } |
---|
771 | | - /* fall through */ |
---|
| 721 | + fallthrough; |
---|
772 | 722 | case TUNER_S0194: |
---|
773 | 723 | fw_lme = fw_c_s0194; |
---|
774 | 724 | ret = request_firmware(&fw, fw_lme, &udev->dev); |
---|
.. | .. |
---|
1004 | 954 | " SHARP:BS2F7HZ0194", " RS2000"}; |
---|
1005 | 955 | char *name = adap->fe[0]->ops.info.name; |
---|
1006 | 956 | |
---|
1007 | | - strlcpy(name, desc, 128); |
---|
| 957 | + strscpy(name, desc, 128); |
---|
1008 | 958 | strlcat(name, fe_name[st->tuner_config], 128); |
---|
1009 | 959 | |
---|
1010 | 960 | return 0; |
---|
.. | .. |
---|
1068 | 1018 | } |
---|
1069 | 1019 | break; |
---|
1070 | 1020 | } |
---|
1071 | | - /* fall through */ |
---|
| 1021 | + fallthrough; |
---|
1072 | 1022 | case 0x22f0: |
---|
1073 | 1023 | st->i2c_gate = 5; |
---|
1074 | 1024 | adap->fe[0] = dvb_attach(m88rs2000_attach, |
---|
.. | .. |
---|
1245 | 1195 | return 0; |
---|
1246 | 1196 | } |
---|
1247 | 1197 | |
---|
1248 | | -static void *lme2510_exit_int(struct dvb_usb_device *d) |
---|
| 1198 | +static void lme2510_exit(struct dvb_usb_device *d) |
---|
1249 | 1199 | { |
---|
1250 | 1200 | struct lme2510_state *st = d->priv; |
---|
1251 | 1201 | struct dvb_usb_adapter *adap = &d->adapter[0]; |
---|
1252 | | - void *buffer = NULL; |
---|
1253 | 1202 | |
---|
1254 | 1203 | if (adap != NULL) { |
---|
1255 | 1204 | lme2510_kill_urb(&adap->stream); |
---|
1256 | 1205 | } |
---|
1257 | 1206 | |
---|
1258 | | - if (st->usb_buffer != NULL) { |
---|
1259 | | - st->i2c_talk_onoff = 1; |
---|
1260 | | - st->signal_level = 0; |
---|
1261 | | - st->signal_sn = 0; |
---|
1262 | | - buffer = st->usb_buffer; |
---|
1263 | | - } |
---|
1264 | | - |
---|
1265 | | - if (st->lme_urb != NULL) { |
---|
| 1207 | + if (st->lme_urb) { |
---|
1266 | 1208 | usb_kill_urb(st->lme_urb); |
---|
1267 | | - usb_free_coherent(d->udev, 128, st->buffer, |
---|
1268 | | - st->lme_urb->transfer_dma); |
---|
| 1209 | + usb_free_urb(st->lme_urb); |
---|
1269 | 1210 | info("Interrupt Service Stopped"); |
---|
1270 | | - } |
---|
1271 | | - |
---|
1272 | | - return buffer; |
---|
1273 | | -} |
---|
1274 | | - |
---|
1275 | | -static void lme2510_exit(struct dvb_usb_device *d) |
---|
1276 | | -{ |
---|
1277 | | - void *usb_buffer; |
---|
1278 | | - |
---|
1279 | | - if (d != NULL) { |
---|
1280 | | - usb_buffer = lme2510_exit_int(d); |
---|
1281 | | - kfree(usb_buffer); |
---|
1282 | 1211 | } |
---|
1283 | 1212 | } |
---|
1284 | 1213 | |
---|
.. | .. |
---|
1288 | 1217 | .bInterfaceNumber = 0, |
---|
1289 | 1218 | .adapter_nr = adapter_nr, |
---|
1290 | 1219 | .size_of_priv = sizeof(struct lme2510_state), |
---|
| 1220 | + .generic_bulk_ctrl_endpoint = 0x01, |
---|
| 1221 | + .generic_bulk_ctrl_endpoint_response = 0x01, |
---|
1291 | 1222 | |
---|
1292 | 1223 | .download_firmware = lme2510_download_firmware, |
---|
1293 | 1224 | |
---|