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

📄 hso.c

📁 linux系统下3G模块USB串口驱动程序源代码最新版本
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** * * Driver for Option High Speed Mobile Devices. * *  Copyright (C) 2008 Option International *                     Filip Aben <f.aben@option.com> *                     Denis Joseph Barrow <d.barow@option.com> *                     Jan Dumon <j.dumon@option.com> *  Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd) *  			<ajb@spheresystems.co.uk> *  Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> *  Copyright (C) 2008 Novell, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, *  USA * * *****************************************************************************//****************************************************************************** * * Description of the device: * * Interface 0:	Contains the IP network interface on the bulk end points. *		The multiplexed serial ports are using the interrupt and *		control endpoints. *		Interrupt contains a bitmap telling which multiplexed *		serialport needs servicing. * * Interface 1:	Diagnostics port, uses bulk only, do not submit urbs until the *		port is opened, as this have a huge impact on the network port *		throughput. * * Interface 2:	Standard modem interface - circuit switched interface, this *		can be used to make a standard ppp connection however it *              should not be used in conjunction with the IP network interface *              enabled for USB performance reasons i.e. if using this set *              ideally disable_net=1. * *****************************************************************************/#include <linux/version.h>#include <linux/autoconf.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/netdevice.h>#include <linux/module.h>#include <linux/ethtool.h>#include <linux/usb.h>#include <linux/timer.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/kmod.h>#define HAVE_RFKILL (defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE))#if (HAVE_RFKILL)#include <linux/rfkill.h>#endif#include <linux/ip.h>#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))#include <linux/uaccess.h>#else#include <asm/uaccess.h>#endif#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))#include <linux/usb/cdc.h>#else#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 11))#include <linux/usb_cdc.h>#else#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x0#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x1#endif#endif#include <net/arp.h>#include <asm/byteorder.h>#include <linux/serial_core.h>#include <linux/serial.h>#if  (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15))#include <linux/mutex.h>#define MUTEX mutex#else#include <asm/semaphore.h>#define MUTEX semaphore#define mutex_init(sem) sema_init(sem, 1)#define mutex_lock(sem) down(sem)#define mutex_unlock(sem) up(sem)#endif  /* ( LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 15) ) */#define NETDEV_HAVE_DEV (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20))#if NETDEV_HAVE_DEV#define netdev_err(net, format, arg...)  dev_err(&net->dev, format, ## arg)#define netdev_warn(net, format, arg...) dev_warn(&net->dev, format, ## arg)#else#define netdev_err(net, format, arg...) printk(KERN_ERR "%s" format ,\					       (char *)(&net->name), ## arg)#define netdev_warn(net, format, arg...) printk(KERN_WARNING "%s" format ,\                                                (char *)(&net->name), ## arg)#endif#ifdef CONFIG_HSO_AUTOPM#if  (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))#warning "CONFIG_HSO_AUTOPM set for kernel version < 2.6.19," \          "it's not supported by the kernel I'm undeffing it."#undef CONFIG_HSO_AUTOPM#endif#endif#define HAVE_RESET_RESUME (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))#if (!HAVE_RFKILL)#define SIOCSETRADIO   (SIOCDEVPRIVATE+4)#endif#if  (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22))static inline void skb_reset_mac_header(struct sk_buff *skb){	skb->mac.raw = skb->data;}#endif#ifdef CONFIG_HSO_AUTOPM#define sCONFIG_HSO_AUTOPM "CONFIG_HSO_AUTOPM "#else#define sCONFIG_HSO_AUTOPM ""#endif#ifdef CONFIG_HSO_DEBUG#define sCONFIG_HSO_DEBUG "CONFIG_HSO_DEBUG "#else#define sCONFIG_HSO_DEBUG ""#endif#define DRIVER_VERSION			"1.12-Option"#define MOD_AUTHOR			"Option Wireless"#define MOD_DESCRIPTION			"USB High Speed Option driver"#define MOD_LICENSE			"GPL"#define HSO_MAX_NET_DEVICES		10#define HSO_MAX_MTU			2048#define DEFAULT_MTU			1500#define DEFAULT_MRU			1500#define CTRL_URB_RX_SIZE		1024#define CTRL_URB_TX_SIZE		64#define BULK_URB_RX_SIZE		4096#define BULK_URB_TX_SIZE		8192#define MUX_BULK_RX_BUF_SIZE		HSO_MAX_MTU#define MUX_BULK_TX_BUF_SIZE		HSO_MAX_MTU#define MUX_BULK_RX_BUF_COUNT		4#define USB_TYPE_OPTION_VENDOR		0x20/* These definitions are used with the struct hso_net flags element *//* - use *_bit operations on it. (bit indices not values.) */#define HSO_NET_RUNNING			0#define	HSO_NET_TX_TIMEOUT		(HZ*10)#define HSO_SERIAL_MAGIC		0x48534f31/* Number of ttys to handle */#define HSO_SERIAL_TTY_MINORS		256#define MAX_RX_URBS			2/*****************************************************************************//* kernel dependent declarations                                             *//*****************************************************************************/#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))#define TERMIOS				termios#define GFP_T				int#define CALLBACK_ARGS			struct urb *urb, struct pt_regs *regs#else	/* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) */#define TERMIOS				ktermios#define GFP_T				gfp_t#define CALLBACK_ARGS			struct urb *urb#endif	/* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) */static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty){	if (tty)		return tty->driver_data;	return NULL;}/*****************************************************************************//* Debugging functions                                                       *//*****************************************************************************/#define D__(lvl_, fmt, arg...)				\	do {						\		printk(lvl_ "[%d:%s]: " fmt "\n",	\		       __LINE__, __func__, ## arg);	\	} while (0)#define D_(lvl, args...)				\	do {						\		if (lvl & debug)			\			D__(KERN_INFO, args);		\	} while (0)#define D1(args...)	D_(0x01, ##args)#define D2(args...)	D_(0x02, ##args)#define D3(args...)	D_(0x04, ##args)#define D4(args...)	D_(0x08, ##args)#define D5(args...)	D_(0x10, ##args)/*****************************************************************************//* Enumerators                                                               *//*****************************************************************************/enum pkt_parse_state {	WAIT_IP,	WAIT_DATA,	WAIT_SYNC};/*****************************************************************************//* Structs                                                                   *//*****************************************************************************/struct hso_shared_int {	struct usb_endpoint_descriptor *intr_endp;	void *shared_intr_buf;	struct urb *shared_intr_urb;	struct usb_device *usb;	int use_count;	int ref_count;	struct MUTEX shared_int_lock;};#define NETDEVICE_HAS_STATS  (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))struct hso_net {	struct hso_device *parent;#if (!NETDEVICE_HAS_STATS)	struct net_device_stats	stats;#endif	struct net_device *net;#if HAVE_RFKILL	struct rfkill *rfkill;#endif	struct usb_endpoint_descriptor *in_endp;	struct usb_endpoint_descriptor *out_endp;	struct urb *mux_bulk_rx_urb_pool[MUX_BULK_RX_BUF_COUNT];	struct urb *mux_bulk_tx_urb;	void *mux_bulk_rx_buf_pool[MUX_BULK_RX_BUF_COUNT];	void *mux_bulk_tx_buf;	struct sk_buff *skb_rx_buf;	struct sk_buff *skb_tx_buf;	enum pkt_parse_state rx_parse_state;	spinlock_t net_lock;	unsigned short rx_buf_size;	unsigned short rx_buf_missing;	struct iphdr rx_ip_hdr;	unsigned long flags;};#if NETDEVICE_HAS_STATS#define STATS(net) ((net)->stats)#else#define STATS(net) (((struct hso_net *)netdev_priv(net))->stats)#endif#define HAVE_TTY_INSERT_FLIP_STRING \(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16))#define HAVE_LDISC_OPS  (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16))enum rx_ctrl_state{	RX_IDLE,	RX_SENT,	RX_PENDING};#define BM_REQUEST_TYPE (0xa1)#define B_NOTIFICATION  (0x20)#define W_VALUE         (0x0)#define W_INDEX         (0x2)#define W_LENGTH        (0x2)#define B_OVERRUN       (0x1<<6)#define B_PARITY        (0x1<<5)#define B_FRAMING       (0x1<<4)#define B_RING_SIGNAL   (0x1<<3)#define B_BREAK         (0x1<<2)#define B_TX_CARRIER    (0x1<<1)#define B_RX_CARRIER    (0x1<<0)struct hso_serial_state_notification {	u8 bmRequestType;	u8 bNotification;	u16 wValue;	u16 wIndex;	u16 wLength;	u16 UART_state_bitmap;} __attribute__((packed));struct hso_tiocmget {	struct MUTEX mutex;	wait_queue_head_t waitq;	int    intr_completed;	struct usb_endpoint_descriptor *endp;	struct urb *urb;	struct hso_serial_state_notification serial_state_notification;	u16    prev_UART_state_bitmap;	struct uart_icount icount;};struct hso_serial {	struct hso_device *parent;	int magic;	u8 minor;	struct hso_shared_int *shared_int;	/* rx/tx urb could be either a bulk urb or a control urb depending	   on which serial port it is used on. */	struct urb *rx_urb[MAX_RX_URBS];	u8 num_rx_urbs;	u8 *rx_data[MAX_RX_URBS];	u16 rx_data_length;	/* should contain allocated length */	struct urb *tx_urb;	u8 *tx_data;	u8 *tx_buffer;	u16 tx_data_length;	/* should contain allocated length */	u16 tx_data_count;	u16 tx_buffer_count;	struct usb_ctrlrequest ctrl_req_tx;	struct usb_ctrlrequest ctrl_req_rx;	struct usb_endpoint_descriptor *in_endp;	struct usb_endpoint_descriptor *out_endp;	enum rx_ctrl_state rx_state;	u8 rts_state;	u8 dtr_state;	unsigned tx_urb_used:1;	/* from usb_serial_port */	struct tty_struct *tty;	int open_count;	spinlock_t serial_lock;	int (*write_data) (struct hso_serial *serial);        /* Hacks required to get flow control	 * working on the serial receive buffers	 * so as not to drop characters on the floor.         */	int  curr_rx_urb_idx;	u16  curr_rx_urb_offset;	u8   rx_urb_filled[MAX_RX_URBS];	struct tasklet_struct unthrottle_tasklet;	struct hso_tiocmget  *tiocmget;};struct hso_mutex_t {	struct MUTEX mutex;	u8 allocated;};struct hso_device {	union {		struct hso_serial *dev_serial;		struct hso_net *dev_net;	} port_data;	u32 port_spec;	u8 usb_gone;#ifdef CONFIG_HSO_AUTOPM	u8 is_active;	struct work_struct async_get_intf;	struct work_struct async_put_intf;#endif	struct usb_device *usb;	struct usb_interface *interface;	struct device *dev;	struct kref ref;	struct hso_mutex_t *mutex;};/* Type of interface */#define HSO_INTF_MASK		0xFF00#define	HSO_INTF_MUX		0x0100#define	HSO_INTF_BULK   	0x0200/* Type of port */#define HSO_PORT_MASK		0xFF#define HSO_PORT_NO_PORT	0x0#define	HSO_PORT_CONTROL	0x1#define	HSO_PORT_APP		0x2#define	HSO_PORT_GPS		0x3#define	HSO_PORT_PCSC		0x4#define	HSO_PORT_APP2		0x5#define HSO_PORT_GPS_CONTROL	0x6#define HSO_PORT_MSD		0x7#define HSO_PORT_VOICE		0x8#define HSO_PORT_DIAG2		0x9#define	HSO_PORT_DIAG		0x10#define	HSO_PORT_MODEM		0x11#define	HSO_PORT_NETWORK	0x12/* Additional device info */#define HSO_INFO_MASK		0xFF000000#define HSO_INFO_CRC_BUG	0x01000000/*****************************************************************************//* Prototypes                                                                *//*****************************************************************************//* Serial driver functions */static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,			       unsigned int set, unsigned int clear);static void ctrl_callback(CALLBACK_ARGS);static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);static void hso_kick_transmit(struct hso_serial *serial);/* Helper functions */static int hso_mux_submit_intr_urb(struct hso_shared_int *mux_int,				   struct usb_device *usb, GFP_T gfp);static void log_usb_status(int status, const char *function);static struct usb_endpoint_descriptor *hso_get_ep(struct usb_interface *intf,						  int type, int dir);static int hso_get_mux_ports(struct usb_interface *intf, unsigned char *ports);static void hso_free_interface(struct usb_interface *intf);static int hso_start_serial_device(struct hso_device *hso_dev, GFP_T flags);static int hso_stop_serial_device(struct hso_device *hso_dev);static int hso_start_net_device(struct hso_device *hso_dev);static void hso_free_shared_int(struct hso_shared_int *shared_int);static int hso_stop_net_device(struct hso_device *hso_dev);static void hso_serial_ref_free(struct kref *ref);static void hso_std_serial_read_bulk_callback(CALLBACK_ARGS);static int hso_mux_serial_read(struct hso_serial *serial);#ifdef CONFIG_HSO_AUTOPMstatic void async_get_intf(struct work_struct *data);static void async_put_intf(struct work_struct *data);static int hso_put_activity(struct hso_device *hso_dev);static int hso_get_activity(struct hso_device *hso_dev);#endifstatic void tiocmget_intr_callback(CALLBACK_ARGS);/*****************************************************************************//* Helping functions                                                         *//*****************************************************************************/static inline struct hso_net *dev2net(struct hso_device *hso_dev){	return hso_dev->port_data.dev_net;}static inline struct hso_serial *dev2ser(struct hso_device *hso_dev){	return hso_dev->port_data.dev_serial;}#if  (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 23))#define safe_usb_unlink_urb usb_unlink_urb#define safe_usb_kill_urb   usb_kill_urb#elsestatic void safe_usb_unlink_urb(struct urb *urb){	if (!urb)

⌨️ 快捷键说明

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