| .. | .. |
|---|
| 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 | |
|---|