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

📄 kobil_sct.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  KOBIL USB Smart Card Terminal Driver * *  Copyright (C) 2002  KOBIL Systems GmbH  *  Author: Thomas Wahrenbruch * *  Contact: linuxusb@kobil.de * *  This program is largely derived from work by the linux-usb group *  and associated source files.  Please see the usb/serial files for *  individual credits and copyrights. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and *  patience. * * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus * (Adapter K), B1 Professional and KAAN Professional (Adapter B) *  * (23/05/2003) tw *      Add support for KAAN SIM * * (12/03/2002) tw *      Fixed bug with Pro-readers and PNP * * (11/13/2002) tw *      Initial version. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/spinlock.h>#include <asm/uaccess.h>#include <linux/usb.h>#include <linux/ioctl.h>#include "kobil_sct.h"#ifdef CONFIG_USB_SERIAL_DEBUG	static int debug = 1;#else	static int debug;#endif#include "usb-serial.h"/* Version Information */#define DRIVER_VERSION "12/03/2002"#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"#define KOBIL_VENDOR_ID	           0x0D46#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012#define KOBIL_USBTWIN_PRODUCT_ID   0x0078#define KOBIL_KAAN_SIM_PRODUCT_ID  0x0081#define KOBIL_TIMEOUT    500#define KOBIL_BUF_LENGTH 300/* Function prototypes */static int  kobil_startup (struct usb_serial *serial);static void kobil_shutdown (struct usb_serial *serial);static int  kobil_open (struct usb_serial_port *port, struct file *filp);static void kobil_close (struct usb_serial_port *port, struct file *filp);static int  kobil_write (struct usb_serial_port *port, int from_user, 			 const unsigned char *buf, int count);static int  kobil_write_room(struct usb_serial_port *port);static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,			unsigned int cmd, unsigned long arg);static void kobil_read_int_callback( struct urb *urb );static void kobil_write_callback( struct urb *purb );static struct usb_device_id id_table [] = {	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) },	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) },	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE (usb, id_table);struct usb_serial_device_type kobil_device = {	.owner =                THIS_MODULE,	.name =			"KOBIL USB smart card terminal",	.id_table =		id_table,	.num_interrupt_in =	NUM_DONT_CARE,	.num_bulk_in =		0,	.num_bulk_out =		0,	.num_ports =		1,	.startup =		kobil_startup,	.shutdown =		kobil_shutdown,	.ioctl =		kobil_ioctl,	.open =			kobil_open,	.close =		kobil_close,	.write =		kobil_write,	.write_room =           kobil_write_room,	.read_int_callback =	kobil_read_int_callback,};struct kobil_private {	int write_int_endpoint_address;	int read_int_endpoint_address;	unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send	int filled;  // index of the last char in buf	int cur_pos; // index of the next char to send in buf	__u16 device_type;	int line_state;	struct termios internal_termios;};static int kobil_startup (struct usb_serial *serial){	int i;	struct kobil_private *priv;	struct usb_device *pdev;	struct usb_config_descriptor *actconfig;	struct usb_interface *interface;	struct usb_interface_descriptor *altsetting;	struct usb_endpoint_descriptor *endpoint;	serial->port->private = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);	if (!serial->port->private){		return -1;	} 	priv = (struct kobil_private *) serial->port->private;	priv->filled = 0;	priv->cur_pos = 0;	priv->device_type = serial->product;	priv->line_state = 0;		switch (priv->device_type){	case KOBIL_ADAPTER_B_PRODUCT_ID:		printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n");		break;	case KOBIL_ADAPTER_K_PRODUCT_ID:		printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");		break;	case KOBIL_USBTWIN_PRODUCT_ID:		printk(KERN_DEBUG "KOBIL USBTWIN detected\n");		break;	case KOBIL_KAAN_SIM_PRODUCT_ID:		printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");		break;	}	// search for the neccessary endpoints	pdev = serial->dev; 	actconfig = pdev->actconfig; 	interface = actconfig->interface;	altsetting = interface->altsetting; 	endpoint = altsetting->endpoint;   	for (i = 0; i < altsetting->bNumEndpoints; i++) {		endpoint = &altsetting->endpoint[i];		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&  		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {		 	dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->bEndpointAddress);		 	priv->write_int_endpoint_address = endpoint->bEndpointAddress; 		} 		if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&  		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {		 	dbg("%s Found interrupt in  endpoint. Address: %d", __FUNCTION__, endpoint->bEndpointAddress);		 	priv->read_int_endpoint_address = endpoint->bEndpointAddress;	 	}	}	return 0;}static void kobil_shutdown (struct usb_serial *serial){	int i;  	dbg("%s - port %d", __FUNCTION__, serial->port->number);	for (i=0; i < serial->num_ports; ++i) {		while (serial->port[i].open_count > 0) {			kobil_close (&serial->port[i], NULL);		}		if (serial->port[i].private) {			kfree(serial->port[i].private);		}	} }static int kobil_open (struct usb_serial_port *port, struct file *filp){	int i, result = 0;	struct kobil_private *priv;	unsigned char *transfer_buffer;	int transfer_buffer_length = 8;	int write_urb_transfer_buffer_length = 8;	  	dbg("%s - port %d", __FUNCTION__, port->number);	priv = (struct kobil_private *) port->private;	priv->line_state = 0;	if (port_paranoia_check (port, __FUNCTION__))		return -ENODEV;		// someone sets the dev to 0 if the close method has been called	port->interrupt_in_urb->dev = port->serial->dev;		/* force low_latency on so that our tty_push actually forces	 * the data through, otherwise it is scheduled, and with high	 * data rates (like with OHCI) data can get lost.	 */	port->tty->low_latency = 1;	// without this, every push_tty_char is echoed :-(  	port->tty->termios->c_lflag = 0;	port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);	port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;	port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)		// set up internal termios structure 	priv->internal_termios.c_iflag = port->tty->termios->c_iflag;	priv->internal_termios.c_oflag = port->tty->termios->c_oflag;	priv->internal_termios.c_cflag = port->tty->termios->c_cflag;	priv->internal_termios.c_lflag = port->tty->termios->c_lflag;		for (i=0; i<NCCS; i++) {		priv->internal_termios.c_cc[i] = port->tty->termios->c_cc[i];	}		// allocate memory for transfer buffer	transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);  	if (! transfer_buffer) {		return -1;	} else {		memset(transfer_buffer, 0, transfer_buffer_length);	}		// allocate write_urb	if (!port->write_urb) { 		dbg("%s - port %d  Allocating port->write_urb", __FUNCTION__, port->number);		port->write_urb = usb_alloc_urb(0);  		if (!port->write_urb) {			dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number);			kfree(transfer_buffer);			return -1;		}	} 	// allocate memory for write_urb transfer buffer	port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);	if (! port->write_urb->transfer_buffer) {		kfree(transfer_buffer);		return -1;	} 	// get hardware version	result = usb_control_msg( port->serial->dev, 				  usb_rcvctrlpipe(port->serial->dev, 0 ), 				  SUSBCRequest_GetMisc,				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,				  SUSBCR_MSC_GetHWVersion,				  0,				  transfer_buffer,				  transfer_buffer_length,				  KOBIL_TIMEOUT		);	dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result);	dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );		// get firmware version	result = usb_control_msg( port->serial->dev, 				  usb_rcvctrlpipe(port->serial->dev, 0 ), 				  SUSBCRequest_GetMisc,				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,				  SUSBCR_MSC_GetFWVersion,				  0,				  transfer_buffer,				  transfer_buffer_length,				  KOBIL_TIMEOUT		);	dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result);	dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {		// Setting Baudrate, Parity and Stopbits		result = usb_control_msg( port->serial->dev, 					  usb_rcvctrlpipe(port->serial->dev, 0 ), 					  SUSBCRequest_SetBaudRateParityAndStopBits,					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,					  SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit,					  0,					  transfer_buffer,					  0,					  KOBIL_TIMEOUT			);		dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);				// reset all queues		result = usb_control_msg( port->serial->dev, 					  usb_rcvctrlpipe(port->serial->dev, 0 ), 					  SUSBCRequest_Misc,					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,					  SUSBCR_MSC_ResetAllQueues,					  0,					  transfer_buffer,					  0,					  KOBIL_TIMEOUT			);		dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result);	}	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||	    priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {		// start reading (Adapter B 'cause PNP string)		result = usb_submit_urb( port->interrupt_in_urb ); 		dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);	}	kfree(transfer_buffer);	return 0;}static void kobil_close (struct usb_serial_port *port, struct file *filp){	dbg("%s - port %d", __FUNCTION__, port->number);	if (port->write_urb){		usb_unlink_urb( port->write_urb );		usb_free_urb( port->write_urb );		port->write_urb = 0;	}	if (port->interrupt_in_urb){		usb_unlink_urb (port->interrupt_in_urb);	}}static void kobil_read_int_callback( struct urb *purb ){  	int i;	struct usb_serial_port *port = (struct usb_serial_port *) purb->context;	struct tty_struct *tty;

⌨️ 快捷键说明

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