static void flexcop_usb_urb_complete(struct urb *urb) { struct flexcop_usb *fc_usb = urb->context; int i; if (urb->actual_length > 0) deb_ts("urb completed, bufsize: %d actlen; %d\n", urb->transfer_buffer_length, urb->actual_length); 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); flexcop_usb_process_frame(fc_usb, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); } urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } usb_submit_urb(urb,GFP_ATOMIC); }
/* URB stuff for streaming */ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs) { struct dvb_usb_device *d = urb->context; int ptype = usb_pipetype(urb->pipe); int i; u8 *b; deb_ts("'%s' urb completed. feedcount: %d, status: %d, length: %d/%d, pack_num: %d, errors: %d\n", ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", d->feedcount, urb->status,urb->actual_length,urb->transfer_buffer_length, urb->number_of_packets,urb->error_count); switch (urb->status) { case 0: /* success */ case -ETIMEDOUT: /* NAK */ break; case -ECONNRESET: /* kill */ case -ENOENT: case -ESHUTDOWN: return; default: /* error */ deb_ts("urb completition error %d.", urb->status); break; } if (d->feedcount > 0) { if (d->state & DVB_USB_STATE_DVB) { switch (ptype) { case PIPE_ISOCHRONOUS: b = (u8 *) urb->transfer_buffer; for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status != 0) deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status); else if (urb->iso_frame_desc[i].actual_length > 0) { dvb_dmx_swfilter(&d->demux,b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); } urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } debug_dump(b,20,deb_ts); break; case PIPE_BULK: if (urb->actual_length > 0) dvb_dmx_swfilter(&d->demux, (u8 *) urb->transfer_buffer,urb->actual_length); break; default: err("unkown endpoint type in completition handler."); return; } } } usb_submit_urb(urb,GFP_ATOMIC); }
static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length) { u8 *b; int l; deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length); if (fc_usb->tmp_buffer_length > 0) { memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length); fc_usb->tmp_buffer_length += buffer_length; b = fc_usb->tmp_buffer; l = fc_usb->tmp_buffer_length; } else { b=buffer; l=buffer_length; } while (l >= 190) { if (*b == 0xff) { switch (*(b+1) & 0x03) { case 0x01: /* media packet */ if (*(b+2) == 0x47) flexcop_pass_dmx_packets( fc_usb->fc_dev, b+2, 1); else deb_ts( "not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5)); b += 190; l -= 190; break; default: deb_ts("wrong packet type\n"); l = 0; break; } } else { deb_ts("wrong header\n"); l = 0; } } if (l>0) memcpy(fc_usb->tmp_buffer, b, l); fc_usb->tmp_buffer_length = l; }
/* URB stuff for streaming */ static void usb_urb_complete(struct urb *urb) { struct usb_data_stream *stream = urb->context; int ptype = usb_pipetype(urb->pipe); int i; u8 *b; deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n", ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", urb->status,urb->actual_length,urb->transfer_buffer_length, urb->number_of_packets,urb->error_count); switch (urb->status) { case 0: /* success */ case -ETIMEDOUT: /* NAK */ break; case -ECONNRESET: /* kill */ case -ENOENT: case -ESHUTDOWN: return; default: /* error */ deb_ts("urb completition error %d.\n", urb->status); break; } b = (u8 *) urb->transfer_buffer; switch (ptype) { case PIPE_ISOCHRONOUS: for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status != 0) deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status); else if (urb->iso_frame_desc[i].actual_length > 0) stream->complete(stream, b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } debug_dump(b,20,deb_uxfer); break; case PIPE_BULK: if (urb->actual_length > 0) stream->complete(stream, b, urb->actual_length); break; default: err("unkown endpoint type in completition handler."); return; } usb_submit_urb(urb,GFP_ATOMIC); }
static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff) { if (pid == 0x2000) return; deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off"); /* We could use bit magic here to reduce source code size. * I decided against it, but to use the real register names */ switch (index) { case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break; case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break; case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break; case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break; case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break; case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break; default: if (fc->has_32_hw_pid_filter && index < 38) { flexcop_ibi_value vpid,vid; /* set the index */ vid = fc->read_ibi_reg(fc,index_reg_310); vid.index_reg_310.index_reg = index - 6; fc->write_ibi_reg(fc,index_reg_310, vid); vpid = fc->read_ibi_reg(fc,pid_n_reg_314); vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; vpid.pid_n_reg_314.PID_enable_bit = onoff; fc->write_ibi_reg(fc,pid_n_reg_314, vpid); } break; } }
static void b2c2_urb_complete(struct urb *urb, struct pt_regs *ptregs) { struct usb_b2c2_usb *b2c2 = urb->context; deb_ts("urb completed, bufsize: %d\n",urb->transfer_buffer_length); // urb_submit_urb(urb,GFP_ATOMIC); enable for real action }
static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff) { if (fc->fullts_streaming_state != onoff) { deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling"); flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff)); flexcop_pid_group_filter_ctrl(fc, onoff); fc->fullts_streaming_state = onoff; } return 0; }
int usb_urb_kill(struct usb_data_stream *stream) { int i; for (i = 0; i < stream->urbs_submitted; i++) { deb_ts("killing URB no. %d.\n",i); /* stop the URB */ usb_kill_urb(stream->urb_list[i]); } stream->urbs_submitted = 0; return 0; }
int dvb_usb_urb_kill(struct dvb_usb_device *d) { int i; for (i = 0; i < d->urbs_submitted; i++) { deb_ts("killing URB no. %d.\n",i); /* stop the URB */ usb_kill_urb(d->urb_list[i]); } d->urbs_submitted = 0; return 0; }
int dvb_usb_urb_submit(struct dvb_usb_device *d) { int i,ret; for (i = 0; i < d->urbs_initialized; i++) { deb_ts("submitting URB no. %d\n",i); if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) { err("could not submit URB no. %d - get them all back",i); dvb_usb_urb_kill(d); return ret; } d->urbs_submitted++; } return 0; }
int usb_urb_submit(struct usb_data_stream *stream) { int i,ret; for (i = 0; i < stream->urbs_initialized; i++) { deb_ts("submitting URB no. %d\n",i); if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) { err("could not submit URB no. %d - get them all back",i); usb_urb_kill(stream); return ret; } stream->urbs_submitted++; } return 0; }
static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb) { int i; for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) if (fc_usb->iso_urb[i] != NULL) { deb_ts("unlinking/killing urb no. %d\n",i); usb_kill_urb(fc_usb->iso_urb[i]); usb_free_urb(fc_usb->iso_urb[i]); } if (fc_usb->iso_buffer != NULL) pci_free_consistent(NULL, fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr); }
static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid, int onoff) { if (pid == 0x2000) return; deb_ts("setting pid: %5d %04x at index %d '%s'\n", pid, pid, index, onoff ? "on" : "off"); switch (index) { case 0: flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff); break; case 1: flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff); break; case 2: flexcop_pid_PCR_PID_ctrl(fc, pid, onoff); break; case 3: flexcop_pid_PMT_PID_ctrl(fc, pid, onoff); break; case 4: flexcop_pid_EMM_PID_ctrl(fc, pid, onoff); break; case 5: flexcop_pid_ECM_PID_ctrl(fc, pid, onoff); break; default: if (fc->has_32_hw_pid_filter && index < 38) { flexcop_ibi_value vpid, vid; vid = fc->read_ibi_reg(fc, index_reg_310); vid.index_reg_310.index_reg = index - 6; fc->write_ibi_reg(fc, index_reg_310, vid); vpid = fc->read_ibi_reg(fc, pid_n_reg_314); vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff; vpid.pid_n_reg_314.PID_enable_bit = onoff; fc->write_ibi_reg(fc, pid_n_reg_314, vpid); } break; } }
static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) { u16 frame_size = le16_to_cpu( fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size, i, j, ret; int buffer_offset = 0; deb_ts("creating %d iso-urbs with %d frames " "each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize); fc_usb->iso_buffer = pci_alloc_consistent(NULL, bufsize, &fc_usb->dma_addr); if (fc_usb->iso_buffer == NULL) return -ENOMEM; memset(fc_usb->iso_buffer, 0, bufsize); fc_usb->buffer_size = bufsize; /* 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_ATOMIC); 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); urb->dev = fc_usb->udev; urb->context = fc_usb; urb->complete = flexcop_usb_urb_complete; urb->pipe = B2C2_USB_DATA_PIPE; urb->transfer_flags = URB_ISO_ASAP; urb->interval = 1; urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO; urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO; urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset; buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { deb_ts("urb no: %d, frame: %d, frame_offset: %d\n", i, j, frame_offset); urb->iso_frame_desc[j].offset = frame_offset; urb->iso_frame_desc[j].length = frame_size; frame_offset += frame_size; } if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) { err("submitting urb %d failed with %d.", i, ret); goto urb_error; } deb_ts("submitted urb no. %d.\n",i); } /* SRAM */ flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB); flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS); flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1); return 0; urb_error: flexcop_usb_transfer_exit(fc_usb); return ret; }
static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); return dvb_usb_ctrl_feed(dvbdmxfeed,0); }
/* does the complete input transfer handling */ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) { struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv; int newfeedcount, ret; if (adap == NULL) return -ENODEV; if ((adap->active_fe < 0) || (adap->active_fe >= adap->num_frontends_initialized)) { return -EINVAL; } newfeedcount = adap->feedcount + (onoff ? 1 : -1); /* stop feed before setting a new pid if there will be no pid anymore */ if (newfeedcount == 0) { deb_ts("stop feeding\n"); usb_urb_kill(&adap->fe_adap[adap->active_fe].stream); if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) { ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0); if (ret < 0) { err("error while stopping stream."); return ret; } } } adap->feedcount = newfeedcount; /* activate the pid on the device specific pid_filter */ deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n", adap->fe_adap[adap->active_fe].pid_filtering ? "yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid, dvbdmxfeed->index, onoff ? "on" : "off"); if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER && adap->fe_adap[adap->active_fe].pid_filtering && adap->props.fe[adap->active_fe].pid_filter != NULL) adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff); /* start the feed if this was the first feed and there is still a feed * for reception. */ if (adap->feedcount == onoff && adap->feedcount > 0) { deb_ts("submitting all URBs\n"); usb_urb_submit(&adap->fe_adap[adap->active_fe].stream); deb_ts("controlling pid parser\n"); if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER && adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF && adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) { ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap, adap->fe_adap[adap->active_fe].pid_filtering); if (ret < 0) { err("could not handle pid_parser"); return ret; } } deb_ts("start feeding\n"); if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) { ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1); if (ret < 0) { err("error while enabling fifo."); return ret; } } } return 0; }
static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) { flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff); deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); }