📄 flexcop-usb.c
字号:
/* * This file is part of linux driver the 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 <patrick.boettcher@desy.de>"/* 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) {\ int i; \ for (i = 0; i < l; i++) method("%02x ", b[i]); \ method("\n");\}#define DEBSTATUS ""#else#define dprintk(level,args...)#define debug_dump(b,l,method)#define DEBSTATUS " (debugging is not enabled)"#endifstatic int debug;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);#undef DEBSTATUS#define deb_info(args...) dprintk(0x01,args)#define deb_ts(args...) dprintk(0x02,args)#define deb_ctrl(args...) dprintk(0x04,args)#define deb_i2c(args...) dprintk(0x08,args)#define deb_v8(args...) dprintk(0x10,args)/* 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 (these are 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 */static int 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 len = usb_control_msg(fc_usb->udev, read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, request, request_type, /* 0xc0 read or 0x40 write*/ wAddress, 0, val, sizeof(u32), B2C2_WAIT_FOR_OPERATION_RDW * HZ); if (len != sizeof(u32)) { err("error while %s dword from %d (%d).",read ? "reading" : "writing", wAddress,wRegOffsPCI); return -EIO; } return 0;}/* * DKT 010817 - add support for V8 memory read/write and flash update */static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, flexcop_usb_request_t req, u8 page, u16 wAddress, u8 *pbBuffer,u32 buflen){// u8 dwRequestType; u8 request_type = USB_TYPE_VENDOR; u16 wIndex; int nWaitTime,pipe,len; wIndex = page << 8; switch (req) { case B2C2_USB_READ_V8_MEM: nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; request_type |= USB_DIR_IN;// dwRequestType = (u8) RTYPE_READ_V8_MEMORY; pipe = B2C2_USB_CTRL_PIPE_IN; break; case B2C2_USB_WRITE_V8_MEM: wIndex |= pbBuffer[0]; request_type |= USB_DIR_OUT; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;// dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY; pipe = B2C2_USB_CTRL_PIPE_OUT; break; case B2C2_USB_FLASH_BLOCK: request_type |= USB_DIR_OUT; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;// dwRequestType = (u8) RTYPE_WRITE_V8_FLASH; pipe = B2C2_USB_CTRL_PIPE_OUT; break; default: deb_info("unsupported request for v8_mem_req %x.\n",req); return -EINVAL; } deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req, wAddress,wIndex,buflen); len = usb_control_msg(fc_usb->udev,pipe, req, request_type, wAddress, wIndex, pbBuffer, buflen, nWaitTime * HZ); debug_dump(pbBuffer,len,deb_v8); return len == buflen ? 0 : -EIO;}#define bytes_left_to_read_on_page(paddr,buflen) \ ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len){ int i,ret = 0; u16 wMax; u32 pagechunk = 0; switch(req) { case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break; case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break; case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break; default: return -EINVAL; break; } for (i = 0; i < len;) { pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len); deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended)); if ((ret = flexcop_usb_v8_memory_req(fc_usb,req, page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */ (addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended), &buf[i],pagechunk)) < 0) return ret; addr += pagechunk; len -= pagechunk; } return 0;}static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended){ return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM, V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6);}#if 0static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, u16 buflen, u8 *pvBuffer){ u16 wValue; u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;// u8 dwRequestType = (u8) RTYPE_GENERIC, int nWaitTime = 2, pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; wValue = (func << 8) | extra; len = usb_control_msg(fc_usb->udev,pipe, B2C2_USB_UTILITY, request_type, wValue, wIndex, pvBuffer, buflen, nWaitTime * HZ); return len == buflen ? 0 : -EIO;}#endif/* usb i2c stuff */static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb, flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen){ u16 wValue, wIndex; int nWaitTime,pipe,len;// u8 dwRequestType; u8 request_type = USB_TYPE_VENDOR; switch (func) { case USB_FUNC_I2C_WRITE: case USB_FUNC_I2C_MULTIWRITE: case USB_FUNC_I2C_REPEATWRITE: /* DKT 020208 - add this to support special case of DiSEqC */ case USB_FUNC_I2C_CHECKWRITE: pipe = B2C2_USB_CTRL_PIPE_OUT; nWaitTime = 2;// dwRequestType = (u8) RTYPE_GENERIC; request_type |= USB_DIR_OUT; break; case USB_FUNC_I2C_READ: case USB_FUNC_I2C_REPEATREAD: pipe = B2C2_USB_CTRL_PIPE_IN; nWaitTime = 2;// dwRequestType = (u8) RTYPE_GENERIC; request_type |= USB_DIR_IN; break; default: deb_info("unsupported function for i2c_req %x\n",func); return -EINVAL; } wValue = (func << 8 ) | (port << 4); wIndex = (chipaddr << 8 ) | addr; deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8); len = usb_control_msg(fc_usb->udev,pipe, req, request_type, wValue, wIndex, buf, buflen, nWaitTime * HZ); return len == buflen ? 0 : -EREMOTEIO;}/* actual bus specific access functions, make sure prototype are/will be equal to pci */static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg){ flexcop_ibi_value val; val.raw = 0; flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1); return val;}static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val){ return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);}static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op, flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len){ if (op == FC_READ) return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len); else return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);}static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length){ u8 *b;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -