⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvb-dibusb-usb.c

📁 h内核
💻 C
字号:
/* * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices  * based on reference design made by DiBcom (http://www.dibcom.fr/) * * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * * see dvb-dibusb-core.c for more copyright details. * * This file contains functions for initializing and handling the  * usb specific stuff. */#include "dvb-dibusb.h"#include <linux/version.h>#include <linux/pci.h>int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,		u16 rlen){	int actlen,ret = -ENOMEM;	if (wbuf == NULL || wlen == 0)		return -EINVAL;	if ((ret = down_interruptible(&dib->usb_sem)))		return ret;	if (dib->feedcount && 		wbuf[0] == DIBUSB_REQ_I2C_WRITE && 		dib->dibdev->dev_cl->id == DIBUSB1_1)		deb_err("BUG: writing to i2c, while TS-streaming destroys the stream."				"(%x reg: %x %x)\n", wbuf[0],wbuf[2],wbuf[3]);				debug_dump(wbuf,wlen);	ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,			dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,			DIBUSB_I2C_TIMEOUT);			if (ret)		err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);	else		ret = actlen != wlen ? -1 : 0;	/* an answer is expected, and no error before */	if (!ret && rbuf && rlen) {		ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,				dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,				DIBUSB_I2C_TIMEOUT);		if (ret)			err("recv bulk message failed: %d",ret);		else {			deb_alot("rlen: %d\n",rlen);			debug_dump(rbuf,actlen);		}	}		up(&dib->usb_sem);	return ret;}/* * Cypress controls */#if 0/*  * #if 0'ing the following functions as they are not in use _now_,  * but probably will be sometime. *//* * do not use this, just a workaround for a bug,  * which will hopefully never occur :). */int dibusb_interrupt_read_loop(struct usb_dibusb *dib){	u8 b[1] = { DIBUSB_REQ_INTR_READ };	return dibusb_write_usb(dib,b,1);}#endif static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len){	return dibusb_readwrite_usb(dib,buf,len,NULL,0);}/* * ioctl for the firmware  */static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen){	u8 b[34];	int size = plen > 32 ? 32 : plen;	memset(b,0,34);	b[0] = DIBUSB_REQ_SET_IOCTL;	b[1] = cmd;	if (size > 0)		memcpy(&b[2],param,size);	return dibusb_write_usb(dib,b,34); //2+size);}/* * ioctl for power control */int dibusb_hw_wakeup(struct dvb_frontend *fe){	struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;	u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };	deb_info("dibusb-device is getting up.\n");	dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);		if (dib->fe_init)		return dib->fe_init(fe);		return 0;}int dibusb_hw_sleep(struct dvb_frontend *fe){	struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;	u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };	deb_info("dibusb-device is going to bed.\n");	dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);	if (dib->fe_sleep)		return dib->fe_sleep(fe);		return 0;}int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode){	u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };	return dibusb_readwrite_usb(dib,b,2,NULL,0);}int dibusb_streaming(struct usb_dibusb *dib,int onoff){	switch (dib->dibdev->dev_cl->id) {		case DIBUSB2_0:			if (onoff)				return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);			else				return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);			break;		case UMT2_0: 			return dibusb_set_streaming_mode(dib,onoff);			break;		default:			break;	}	return 0;}int dibusb_urb_init(struct usb_dibusb *dib){	int ret,i,bufsize,def_pid_parse = 1;		/*	 * when reloading the driver w/o replugging the device 	 * a timeout occures, this helps	 */	usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));	/* allocate the array for the data transfer URBs */	dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);	if (dib->urb_list == NULL)		return -ENOMEM;	memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));	dib->init_state |= DIBUSB_STATE_URB_LIST;		bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;	deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);	/* allocate the actual buffer for the URBs */	if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {		deb_info("not enough memory.\n");		return -ENOMEM;	}	deb_info("allocation complete\n");	memset(dib->buffer,0,bufsize);		dib->init_state |= DIBUSB_STATE_URB_BUF;	/* allocate and submit the URBs */	for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {		if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {			return -ENOMEM;		}		deb_info("submitting URB no. %d\n",i);				usb_fill_bulk_urb( dib->urb_list[i], dib->udev, 				usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),				&dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size], 				dib->dibdev->dev_cl->urb_buffer_size, 				dibusb_urb_complete, dib);				dib->urb_list[i]->transfer_flags = 0;		if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {			err("could not submit buffer urb no. %d\n",i);			return ret;		}		dib->init_state |= DIBUSB_STATE_URB_SUBMIT;	}	/* dib->pid_parse here contains the value of the module parameter */	/* decide if pid parsing can be deactivated:	 * is possible (by speed) and wanted (by user)	 */	switch (dib->dibdev->dev_cl->id) {		case DIBUSB2_0:			if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {				def_pid_parse = 0;				info("running at HIGH speed, will deliver the complete TS.");			} else				info("will use pid_parsing.");			break;		default: 			break;	}	/* from here on it contains the device and user decision */	dib->pid_parse = def_pid_parse;		return 0;}int dibusb_urb_exit(struct usb_dibusb *dib){	int i;	if (dib->init_state & DIBUSB_STATE_URB_LIST) {		for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {			if (dib->urb_list[i] != NULL) {				deb_info("killing URB no. %d.\n",i);				/* stop the URBs */				usb_kill_urb(dib->urb_list[i]);								deb_info("freeing URB no. %d.\n",i);				/* free the URBs */				usb_free_urb(dib->urb_list[i]);			}		}		/* free the urb array */		kfree(dib->urb_list);		dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;		dib->init_state &= ~DIBUSB_STATE_URB_LIST;	}	if (dib->init_state & DIBUSB_STATE_URB_BUF)		pci_free_consistent(NULL,			dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,			dib->buffer,dib->dma_handle);	dib->init_state &= ~DIBUSB_STATE_URB_BUF;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -