option.c

来自「linux 内核源代码」· C语言 代码 · 共 822 行 · 第 1/2 页

C
822
字号
		}		portdata->tx_start_time[i] = jiffies;		buf += todo;		left -= todo;	}	count -= left;	dbg("%s: wrote (did %d)", __FUNCTION__, count);	return count;}static void option_indat_callback(struct urb *urb){	int err;	int endpoint;	struct usb_serial_port *port;	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;	int status = urb->status;	dbg("%s: %p", __FUNCTION__, urb);	endpoint = usb_pipeendpoint(urb->pipe);	port = (struct usb_serial_port *) urb->context;	if (status) {		dbg("%s: nonzero status: %d on endpoint %02x.",		    __FUNCTION__, status, endpoint);	} else {		tty = port->tty;		if (urb->actual_length) {			tty_buffer_request_room(tty, urb->actual_length);			tty_insert_flip_string(tty, data, urb->actual_length);			tty_flip_buffer_push(tty);		} else {			dbg("%s: empty read urb received", __FUNCTION__);		}		/* Resubmit urb so we continue receiving */		if (port->open_count && status != -ESHUTDOWN) {			err = usb_submit_urb(urb, GFP_ATOMIC);			if (err)				printk(KERN_ERR "%s: resubmit read urb failed. "					"(%d)", __FUNCTION__, err);		}	}	return;}static void option_outdat_callback(struct urb *urb){	struct usb_serial_port *port;	struct option_port_private *portdata;	int i;	dbg("%s", __FUNCTION__);	port = (struct usb_serial_port *) urb->context;	usb_serial_port_softint(port);	portdata = usb_get_serial_port_data(port);	for (i = 0; i < N_OUT_URB; ++i) {		if (portdata->out_urbs[i] == urb) {			smp_mb__before_clear_bit();			clear_bit(i, &portdata->out_busy);			break;		}	}}static void option_instat_callback(struct urb *urb){	int err;	int status = urb->status;	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;	struct option_port_private *portdata = usb_get_serial_port_data(port);	struct usb_serial *serial = port->serial;	dbg("%s", __FUNCTION__);	dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);	if (status == 0) {		struct usb_ctrlrequest *req_pkt =				(struct usb_ctrlrequest *)urb->transfer_buffer;		if (!req_pkt) {			dbg("%s: NULL req_pkt\n", __FUNCTION__);			return;		}		if ((req_pkt->bRequestType == 0xA1) &&				(req_pkt->bRequest == 0x20)) {			int old_dcd_state;			unsigned char signals = *((unsigned char *)					urb->transfer_buffer +					sizeof(struct usb_ctrlrequest));			dbg("%s: signal x%x", __FUNCTION__, signals);			old_dcd_state = portdata->dcd_state;			portdata->cts_state = 1;			portdata->dcd_state = ((signals & 0x01) ? 1 : 0);			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);			portdata->ri_state = ((signals & 0x08) ? 1 : 0);			if (port->tty && !C_CLOCAL(port->tty) &&					old_dcd_state && !portdata->dcd_state)				tty_hangup(port->tty);		} else {			dbg("%s: type %x req %x", __FUNCTION__,				req_pkt->bRequestType,req_pkt->bRequest);		}	} else		dbg("%s: error %d", __FUNCTION__, status);	/* Resubmit urb so we continue receiving IRQ data */	if (status != -ESHUTDOWN) {		urb->dev = serial->dev;		err = usb_submit_urb(urb, GFP_ATOMIC);		if (err)			dbg("%s: resubmit intr urb failed. (%d)",				__FUNCTION__, err);	}}static int option_write_room(struct usb_serial_port *port){	struct option_port_private *portdata;	int i;	int data_len = 0;	struct urb *this_urb;	portdata = usb_get_serial_port_data(port);	for (i=0; i < N_OUT_URB; i++) {		this_urb = portdata->out_urbs[i];		if (this_urb && !test_bit(i, &portdata->out_busy))			data_len += OUT_BUFLEN;	}	dbg("%s: %d", __FUNCTION__, data_len);	return data_len;}static int option_chars_in_buffer(struct usb_serial_port *port){	struct option_port_private *portdata;	int i;	int data_len = 0;	struct urb *this_urb;	portdata = usb_get_serial_port_data(port);	for (i=0; i < N_OUT_URB; i++) {		this_urb = portdata->out_urbs[i];		if (this_urb && test_bit(i, &portdata->out_busy))			data_len += this_urb->transfer_buffer_length;	}	dbg("%s: %d", __FUNCTION__, data_len);	return data_len;}static int option_open(struct usb_serial_port *port, struct file *filp){	struct option_port_private *portdata;	struct usb_serial *serial = port->serial;	int i, err;	struct urb *urb;	portdata = usb_get_serial_port_data(port);	dbg("%s", __FUNCTION__);	/* Set some sane defaults */	portdata->rts_state = 1;	portdata->dtr_state = 1;	/* Reset low level data toggle and start reading from endpoints */	for (i = 0; i < N_IN_URB; i++) {		urb = portdata->in_urbs[i];		if (! urb)			continue;		if (urb->dev != serial->dev) {			dbg("%s: dev %p != %p", __FUNCTION__,				urb->dev, serial->dev);			continue;		}		/*		 * make sure endpoint data toggle is synchronized with the		 * device		 */		usb_clear_halt(urb->dev, urb->pipe);		err = usb_submit_urb(urb, GFP_KERNEL);		if (err) {			dbg("%s: submit urb %d failed (%d) %d",				__FUNCTION__, i, err,				urb->transfer_buffer_length);		}	}	/* Reset low level data toggle on out endpoints */	for (i = 0; i < N_OUT_URB; i++) {		urb = portdata->out_urbs[i];		if (! urb)			continue;		urb->dev = serial->dev;		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),				usb_pipeout(urb->pipe), 0); */	}	port->tty->low_latency = 1;	option_send_setup(port);	return (0);}static void option_close(struct usb_serial_port *port, struct file *filp){	int i;	struct usb_serial *serial = port->serial;	struct option_port_private *portdata;	dbg("%s", __FUNCTION__);	portdata = usb_get_serial_port_data(port);	portdata->rts_state = 0;	portdata->dtr_state = 0;	if (serial->dev) {		option_send_setup(port);		/* Stop reading/writing urbs */		for (i = 0; i < N_IN_URB; i++)			usb_kill_urb(portdata->in_urbs[i]);		for (i = 0; i < N_OUT_URB; i++)			usb_kill_urb(portdata->out_urbs[i]);	}	port->tty = NULL;}/* Helper functions used by option_setup_urbs */static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,		int dir, void *ctx, char *buf, int len,		void (*callback)(struct urb *)){	struct urb *urb;	if (endpoint == -1)		return NULL;		/* endpoint not needed */	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */	if (urb == NULL) {		dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);		return NULL;	}		/* Fill URB using supplied data. */	usb_fill_bulk_urb(urb, serial->dev,		      usb_sndbulkpipe(serial->dev, endpoint) | dir,		      buf, len, callback, ctx);	return urb;}/* Setup urbs */static void option_setup_urbs(struct usb_serial *serial){	int i,j;	struct usb_serial_port *port;	struct option_port_private *portdata;	dbg("%s", __FUNCTION__);	for (i = 0; i < serial->num_ports; i++) {		port = serial->port[i];		portdata = usb_get_serial_port_data(port);	/* Do indat endpoints first */		for (j = 0; j < N_IN_URB; ++j) {			portdata->in_urbs[j] = option_setup_urb (serial,                  	port->bulk_in_endpointAddress, USB_DIR_IN, port,                  	portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);		}		/* outdat endpoints */		for (j = 0; j < N_OUT_URB; ++j) {			portdata->out_urbs[j] = option_setup_urb (serial,                  	port->bulk_out_endpointAddress, USB_DIR_OUT, port,                  	portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);		}	}}static int option_send_setup(struct usb_serial_port *port){	struct usb_serial *serial = port->serial;	struct option_port_private *portdata;	dbg("%s", __FUNCTION__);	if (port->number != 0)		return 0;	portdata = usb_get_serial_port_data(port);	if (port->tty) {		int val = 0;		if (portdata->dtr_state)			val |= 0x01;		if (portdata->rts_state)			val |= 0x02;		return usb_control_msg(serial->dev,				usb_rcvctrlpipe(serial->dev, 0),				0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);	}	return 0;}static int option_startup(struct usb_serial *serial){	int i, err;	struct usb_serial_port *port;	struct option_port_private *portdata;	dbg("%s", __FUNCTION__);	/* Now setup per port private data */	for (i = 0; i < serial->num_ports; i++) {		port = serial->port[i];		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);		if (!portdata) {			dbg("%s: kmalloc for option_port_private (%d) failed!.",					__FUNCTION__, i);			return (1);		}		usb_set_serial_port_data(port, portdata);		if (! port->interrupt_in_urb)			continue;		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);		if (err)			dbg("%s: submit irq_in urb failed %d",				__FUNCTION__, err);	}	option_setup_urbs(serial);	return (0);}static void option_shutdown(struct usb_serial *serial){	int i, j;	struct usb_serial_port *port;	struct option_port_private *portdata;	dbg("%s", __FUNCTION__);	/* Stop reading/writing urbs */	for (i = 0; i < serial->num_ports; ++i) {		port = serial->port[i];		portdata = usb_get_serial_port_data(port);		for (j = 0; j < N_IN_URB; j++)			usb_kill_urb(portdata->in_urbs[j]);		for (j = 0; j < N_OUT_URB; j++)			usb_kill_urb(portdata->out_urbs[j]);	}	/* Now free them */	for (i = 0; i < serial->num_ports; ++i) {		port = serial->port[i];		portdata = usb_get_serial_port_data(port);		for (j = 0; j < N_IN_URB; j++) {			if (portdata->in_urbs[j]) {				usb_free_urb(portdata->in_urbs[j]);				portdata->in_urbs[j] = NULL;			}		}		for (j = 0; j < N_OUT_URB; j++) {			if (portdata->out_urbs[j]) {				usb_free_urb(portdata->out_urbs[j]);				portdata->out_urbs[j] = NULL;			}		}	}	/* Now free per port private data */	for (i = 0; i < serial->num_ports; i++) {		port = serial->port[i];		kfree(usb_get_serial_port_data(port));	}}MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_VERSION(DRIVER_VERSION);MODULE_LICENSE("GPL");#ifdef CONFIG_USB_DEBUGmodule_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug messages");#endif

⌨️ 快捷键说明

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