// SPDX-License-Identifier: GPL-2.0-only /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop-usb.c - covers the USB part * see flexcop.c for copyright information
*/ #define FC_LOG_PREFIX "flexcop_usb" #include"flexcop-usb.h" #include"flexcop-common.h"
/* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" #define DRIVER_AUTHOR "Patrick Boettcher "
/* debug */ #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #define dprintk(level, args...) \ do { if ((debug & (level))) printk(args); } while (0)
#define debug_dump(b, l, method) do {\ int i; \ for (i = 0; i < l; i++) \
method("%02x ", b[i]); \
method("\n"); \
} while (0)
#define DEBSTATUS "" #else #define dprintk(level, args...) no_printk(args) #define debug_dump(b, l, method) do { } while (0) #define DEBSTATUS " (debugging is not enabled)" #endif
/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits * in the IBI address, to make the V8 code simpler. * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used) * in general: 0000 0HHH 000L LL00 * IBI ADDRESS FORMAT: RHHH BLLL * * where R is the read(1)/write(0) bit, B is the busy bit * and HHH and LLL are the two sets of three bits from the PCI address.
*/ #define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \
(((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) #define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \
(((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
/* * DKT 020228 * - forget about this VENDOR_BUFFER_SIZE, read and write register * deal with DWORD or 4 bytes, that should be should from now on * - from now on, we don't support anything older than firm 1.00 * I eliminated the write register as a 2 trip of writing hi word and lo word * and force this to write only 4 bytes at a time. * NOTE: this should work with all the firmware from 1.00 and newer
*/ staticint flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read)
{ struct flexcop_usb *fc_usb = fc->bus_specific;
u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
(read ? 0x80 : 0); int ret;
mutex_lock(&fc_usb->data_mutex); if (!read)
memcpy(fc_usb->data, val, sizeof(*val));
for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status < 0) {
err("iso frame descriptor %d has an error: %d\n", i,
urb->iso_frame_desc[i].status);
} else if (urb->iso_frame_desc[i].actual_length > 0) {
deb_ts("passed %d bytes to the demux\n",
urb->iso_frame_desc[i].actual_length);
/* creating iso urbs */ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,
GFP_KERNEL); if (fc_usb->iso_urb[i] == NULL) {
ret = -ENOMEM; goto urb_error;
}
}
/* initialising and submitting iso urbs */ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { int frame_offset = 0; struct urb *urb = fc_usb->iso_urb[i];
deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",
i, buffer_offset);
staticint flexcop_usb_init(struct flexcop_usb *fc_usb)
{ struct usb_host_interface *alt; int ret;
/* use the alternate setting with the largest buffer */
ret = usb_set_interface(fc_usb->udev, 0, 1); if (ret) {
err("set interface failed."); return ret;
}
alt = fc_usb->uintf->cur_altsetting;
if (alt->desc.bNumEndpoints < 2) return -ENODEV; if (!usb_endpoint_is_isoc_in(&alt->endpoint[0].desc)) return -ENODEV;
switch (fc_usb->udev->speed) { case USB_SPEED_LOW:
err("cannot handle USB speed because it is too slow."); return -ENODEV; break; case USB_SPEED_FULL:
info("running at FULL speed."); break; case USB_SPEED_HIGH:
info("running at HIGH speed."); break; case USB_SPEED_SUPER:
info("running at SUPER speed."); break; case USB_SPEED_SUPER_PLUS:
info("running at SUPER+ speed."); break; case USB_SPEED_UNKNOWN: default:
err("cannot handle USB speed because it is unknown."); return -ENODEV;
}
usb_set_intfdata(fc_usb->uintf, fc_usb); return 0;
}
/* usb specific object needed to register this driver with the usb subsystem */ staticstruct usb_driver flexcop_usb_driver = {
.name = "b2c2_flexcop_usb",
.probe = flexcop_usb_probe,
.disconnect = flexcop_usb_disconnect,
.id_table = flexcop_usb_table,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.