int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) { int ret = 0; #else #define deb_info(args...) d; #endif u8 *buf = d->priv; buf[0] = cmd; if (outlen > 19) outlen = 19; if (inlen > 11) inlen = 11; ret = mutex_lock_interruptible(&d->usb_mutex); if (ret) return ret; if (out != NULL && outlen > 0) memcpy(&buf[1], out, outlen); deb_xfer("out buffer: "); debug_dump(buf, outlen+1, deb_xfer); if (usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 20, 2000) != 20) { err("USB control message 'out' went wrong."); ret = -EIO; goto unlock; } msleep(msec); if (usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, buf, 12, 2000) != 12) { err("USB control message 'in' went wrong."); ret = -EIO; goto unlock; } deb_xfer("in buffer: "); debug_dump(buf, 12, deb_xfer); if (in != NULL && inlen > 0) memcpy(in, &buf[1], inlen); unlock: mutex_unlock(&d->usb_mutex); return ret; }
int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) { int ret = 0; u8 inbuf[12] = { 0 }, outbuf[20] = { 0 }; outbuf[0] = cmd; if (outlen > 19) outlen = 19; if (inlen > 11) inlen = 11; if (out != NULL && outlen > 0) memcpy(&outbuf[1], out, outlen); deb_xfer("out buffer: "); debug_dump(outbuf,outlen+1,deb_xfer); if ((ret = down_interruptible(&d->usb_sem))) return ret; if (usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, outbuf, 20, 2000) != 20) { err("USB control message 'out' went wrong."); ret = -EIO; goto unlock; } msleep(msec); if (usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, inbuf, 12, 2000) != 12) { err("USB control message 'in' went wrong."); ret = -EIO; goto unlock; } deb_xfer("in buffer: "); debug_dump(inbuf,12,deb_xfer); if (in != NULL && inlen > 0) memcpy(in,&inbuf[1],inlen); unlock: up(&d->usb_sem); return ret; }
int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen, int delay_ms) { int actlen,ret = -ENOMEM; if (!d || wbuf == NULL || wlen == 0) return -EINVAL; if (d->props.generic_bulk_ctrl_endpoint == 0) { err("endpoint for generic control not specified."); return -EINVAL; } if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; deb_xfer(">>> "); debug_dump(wbuf,wlen,deb_xfer); ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, 2000); if (ret) err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); else ret = actlen != wlen ? -1 : 0; if (!ret && rbuf && rlen) { if (delay_ms) msleep(delay_ms); ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint_response ? d->props.generic_bulk_ctrl_endpoint_response : d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, 2000); if (ret) err("recv bulk message failed: %d",ret); else { deb_xfer("<<< "); debug_dump(rbuf,actlen,deb_xfer); } } mutex_unlock(&d->usb_mutex); return ret; }
static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff) { struct dib3000_state *state = fe->demodulator_priv; deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling"); wr(DIB3000MB_REG_PID_PARSE,onoff); return 0; }
static int __az6007_write(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); debug_dump(b, blen, deb_xfer); if (blen > 64) { err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n", blen); return -EOPNOTSUPP; } ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value, index, b, blen, 5000); if (ret != blen) { err("usb write operation failed. (%d)", ret); return -EIO; } return 0; }
static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff) { struct dib3000_state *state = fe->demodulator_priv; deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling"); if (onoff) { wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE); } else { wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT); } return 0; }
/** * Indirect I2C access to the PLL via FE. * whole I2C protocol data to the PLL is sent via the FE's I2C register. * This is done by a control msg to the FE with the I2C data accompanied, and * a specific USB request number is assigned for that purpose. * * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE). * TODO: refoctored, smarter i2c functions. */ static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { u16 index = wbuf[0]; /* must be JDVBT90502_2ND_I2C_REG(=0xFE) */ u16 value = addr << (8 + 1); int wo = (rbuf == NULL || rlen == 0); /* write only */ u8 req, type; deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n", wbuf[1], wbuf[0], wlen - 1); if (wo && wlen >= 2) { req = GL861_REQ_I2C_DATA_CTRL_WRITE; type = GL861_WRITE; udelay(20); return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), req, type, value, index, &wbuf[1], wlen - 1, 2000); } deb_xfer("not supported ctrl-msg, aborting."); return -EINVAL; }
/* Download firmware sub */ static int asv5211_send_firm(struct usb_device *udev, u8 req, u16 index, void *data, u16 value, u16 size) { int ret; deb_xfer("USB control msg: 40 %02x %04x %04x %04x\n", req, value, index, size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, data, size, 5000); if (ret != size) { err("failed to download firmware at %04x (%04x)", value, ret); return -EIO; } return 0; }
/* normal I2C access (without extra data arguments). * write to the register wbuf[0] at I2C address addr with the value wbuf[1], * or read from the register wbuf[0]. * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3 */ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { u16 index; u16 value = addr << (8 + 1); int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 req, type; unsigned int pipe; /* special case for the indirect I2C access to the PLL via FE, */ if (addr == friio_fe_config.demod_address && wbuf[0] == JDVBT90502_2ND_I2C_REG) return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen); if (wo) { req = GL861_REQ_I2C_WRITE; type = GL861_WRITE; pipe = usb_sndctrlpipe(d->udev, 0); } else { /* rw */ req = GL861_REQ_I2C_READ; type = GL861_READ; pipe = usb_rcvctrlpipe(d->udev, 0); } switch (wlen) { case 1: index = wbuf[0]; break; case 2: index = wbuf[0]; value = value + wbuf[1]; break; case 3: /* special case for 16bit register-address */ index = (wbuf[2] << 8) | wbuf[0]; value = value + wbuf[1]; break; default: deb_xfer("wlen = %x, aborting.", wlen); return -EINVAL; } msleep(1); return usb_control_msg(d->udev, pipe, req, type, value, index, rbuf, rlen, 2000); }
int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); if ((ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), req, USB_TYPE_VENDOR | USB_DIR_OUT, value,index,b,blen, 2000)) != blen) { warn("usb out operation failed. (%d)",ret); return -EIO; } else return 0; }
static int __az6007_read(struct usb_device *udev, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), req, USB_TYPE_VENDOR | USB_DIR_IN, value, index, b, blen, 5000); if (ret < 0) { warn("usb read operation failed. (%d)", ret); return -EIO; } deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); debug_dump(b, blen, deb_xfer); return ret; }
static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d->priv; int act_len, ret; u8 buf[64]; if (slen > sizeof(buf)) slen = sizeof(buf); memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) return -EAGAIN; /* We need receive one message more after dvb_usb_generic_rw due to weird transaction flow, which is 1 x send + 2 x receive. */ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); if (!ret) { /* receive 2nd answer */ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); if (ret) err("%s: recv bulk message failed: %d", __func__, ret); else { deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); } } /* read request, copy returned data to return buf */ if (!ret && rbuf && rlen) memcpy(rbuf, buf, rlen); mutex_unlock(&anysee_usb_mutex); return ret; }
static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) { struct anysee_state *state = d->priv; int act_len, ret; u8 buf[64]; if (slen > sizeof(buf)) slen = sizeof(buf); memcpy(&buf[0], sbuf, slen); buf[60] = state->seq++; if (mutex_lock_interruptible(&anysee_usb_mutex) < 0) return -EAGAIN; ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); if (!ret) { ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), &act_len, 2000); if (ret) err("%s: recv bulk message failed: %d", __func__, ret); else { deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); } } if (!ret && rbuf && rlen) memcpy(rbuf, buf, rlen); mutex_unlock(&anysee_usb_mutex); return ret; }
int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) { int ret = -1; ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), req, USB_TYPE_VENDOR | USB_DIR_IN, value,index,b,blen, 2000); if (ret < 0) { warn("usb in operation failed. (%d)", ret); ret = -EIO; } else ret = 0; deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); debug_dump(b,blen,deb_xfer); return ret; }
static int af9015_rw_udev(struct usb_device *udev, struct req_t *req) { #define BUF_LEN 63 #define REQ_HDR_LEN 8 /* send header size */ #define ACK_HDR_LEN 2 /* rece header size */ int act_len, ret; u8 buf[BUF_LEN]; u8 write = 1; u8 msg_len = REQ_HDR_LEN; static u8 seq; /* packet sequence number */ if (mutex_lock_interruptible(&af9015_usb_mutex) < 0) return -EAGAIN; buf[0] = req->cmd; buf[1] = seq++; buf[2] = req->i2c_addr; buf[3] = req->addr >> 8; buf[4] = req->addr & 0xff; buf[5] = req->mbox; buf[6] = req->addr_len; buf[7] = req->data_len; switch (req->cmd) { case GET_CONFIG: case READ_MEMORY: case RECONNECT_USB: write = 0; break; case READ_I2C: write = 0; buf[2] |= 0x01; /* set I2C direction */ case WRITE_I2C: buf[0] = READ_WRITE_I2C; break; case WRITE_MEMORY: if (((req->addr & 0xff00) == 0xff00) || ((req->addr & 0xff00) == 0xae00)) buf[0] = WRITE_VIRTUAL_MEMORY; case WRITE_VIRTUAL_MEMORY: case COPY_FIRMWARE: case DOWNLOAD_FIRMWARE: case BOOT: break; default: err("unknown command:%d", req->cmd); ret = -1; goto error_unlock; } /* buffer overflow check */ if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) || (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) { err("too much data; cmd:%d len:%d", req->cmd, req->data_len); ret = -EINVAL; goto error_unlock; } /* write requested */ if (write) { memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len); msg_len += req->data_len; } deb_xfer(">>> "); debug_dump(buf, msg_len, deb_xfer); /* send req */ ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, &act_len, AF9015_USB_TIMEOUT); if (ret) err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len); else if (act_len != msg_len) ret = -1; /* all data is not send */ if (ret) goto error_unlock; /* no ack for those packets */ if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB) goto exit_unlock; /* write receives seq + status = 2 bytes read receives seq + status + data = 2 + N bytes */ msg_len = ACK_HDR_LEN; if (!write) msg_len += req->data_len; ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, &act_len, AF9015_USB_TIMEOUT); if (ret) { err("recv bulk message failed:%d", ret); ret = -1; goto error_unlock; } deb_xfer("<<< "); debug_dump(buf, act_len, deb_xfer); /* check status */ if (buf[1]) { err("command failed:%d", buf[1]); ret = -1; goto error_unlock; } /* read request, copy returned data to return buf */ if (!write) memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len); error_unlock: exit_unlock: mutex_unlock(&af9015_usb_mutex); return ret; }
static int lme2510_load_firmware_by_num(struct usb_device *dev, const struct firmware *fw, u8 num) { u8 *b, *p; u8 msg[] = { 0x06, 0x00, 0x54, 0x80, 0x08 }; int pl = 50, ret = 0, i, actlen; info("start downloading lme2510 firmware"); p = kmalloc(53, GFP_KERNEL); b = kmalloc(1, GFP_KERNEL); if ((p != NULL) && (b != NULL)) { for (i = 0; i < fw->size; i += 50) { if ((i + 50) < fw->size){ pl = 50; p[0] = num; } else { pl = fw->size - i; p[0] = 0x80 | num; } p[1] = pl - 1; memcpy(p + 2, fw->data + i, pl); p[pl + 2] = zum(p + 2, pl); deb_xfer(">>> "); debug_dump(p, pl + 3, deb_xfer); ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 0x01), p, pl + 3, &actlen, 2000); ret |= usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x81), b, 1, &actlen, 2000); if ((ret != 0) || (b[0]!= 0x88)) { err("error while transferring firmware %d: %d, " "answer: 0x%02x\n", num, ret, b[0]); ret = -EINVAL; break; } } } memcpy(p, &msg[0], 5); usb_clear_halt(dev, usb_sndbulkpipe(dev, 0x01)); ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 0x01), p, 5, &actlen, 2000); usb_clear_halt(dev, usb_rcvbulkpipe(dev, 0x81)); ret |= usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x81), b, 1, &actlen, 2000); if ((ret != 0) || (b[0]!= 0x77)) { err("error after transferring firmware %d: %d, " "answer: 0x%02x\n", num, ret, b[0]); ret = -EINVAL; } kfree(p); kfree(b); return ret; };