📄 visor.c
字号:
dbg("%s - port %d", __FUNCTION__, port->number); /* shutdown our urbs */ usb_kill_urb(port->read_urb); if (port->interrupt_in_urb) usb_kill_urb(port->interrupt_in_urb); /* Try to send shutdown message, if the device is gone, this will just fail. */ transfer_buffer = kmalloc (0x12, GFP_KERNEL); if (transfer_buffer) { usb_control_msg (port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), VISOR_CLOSE_NOTIFICATION, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); kfree (transfer_buffer); } if (stats) dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n", priv->bytes_in, priv->bytes_out);}static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count){ struct visor_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; struct urb *urb; unsigned char *buffer; unsigned long flags; int status; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - write limit hit\n", __FUNCTION__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); buffer = kmalloc (count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); return -ENOMEM; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { dev_err(&port->dev, "no more free urbs\n"); kfree (buffer); return -ENOMEM; } memcpy (buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); usb_fill_bulk_urb (urb, serial->dev, usb_sndbulkpipe (serial->dev, port->bulk_out_endpointAddress), buffer, count, visor_write_bulk_callback, port); /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __FUNCTION__, status); count = status; kfree (buffer); } else { spin_lock_irqsave(&priv->lock, flags); ++priv->outstanding_urbs; priv->bytes_out += count; spin_unlock_irqrestore(&priv->lock, flags); } /* we are done with this urb, so let the host driver * really free it when it is finished with it */ usb_free_urb (urb); return count;}static int visor_write_room (struct usb_serial_port *port){ dbg("%s - port %d", __FUNCTION__, port->number); /* * We really can take anything the user throws at us * but let's pick a nice big number to tell the tty * layer that we have lots of free space */ return 2048;}static int visor_chars_in_buffer (struct usb_serial_port *port){ dbg("%s - port %d", __FUNCTION__, port->number); /* * We can't really account for how much data we * have sent out, but hasn't made it through to the * device, so just tell the tty layer that everything * is flushed. */ return 0;}static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree (urb->transfer_buffer); dbg("%s - port %d", __FUNCTION__, port->number); if (urb->status) dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; spin_unlock_irqrestore(&priv->lock, flags); schedule_work(&port->work);}static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct visor_private *priv = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; unsigned long flags; int throttled; int result; dbg("%s - port %d", __FUNCTION__, port->number); if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); return; } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); tty = port->tty; if (tty && 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); } spin_lock_irqsave(&priv->lock, flags); priv->bytes_in += urb->actual_length; throttled = priv->throttled; spin_unlock_irqrestore(&priv->lock, flags); /* Continue trying to always read if we should */ if (!throttled) { usb_fill_bulk_urb (port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, visor_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); } return;}static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; int result; switch (urb->status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; } /* * This information is still unknown what it can be used for. * If anyone has an idea, please let the author know... * * Rumor has it this endpoint is used to notify when data * is ready to be read from the bulk ones. */ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer);exit: result = usb_submit_urb (urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __FUNCTION__, result);}static void visor_throttle (struct usb_serial_port *port){ struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); priv->throttled = 1; spin_unlock_irqrestore(&priv->lock, flags);}static void visor_unthrottle (struct usb_serial_port *port){ struct visor_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); priv->throttled = 0; spin_unlock_irqrestore(&priv->lock, flags); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);}static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id){ struct device *dev = &serial->dev->dev; struct visor_connection_info *connection_info; unsigned char *transfer_buffer; char *string; int retval = 0; int i; int num_ports = 0; dbg("%s", __FUNCTION__); transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL); if (!transfer_buffer) { dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __FUNCTION__, sizeof(*connection_info)); return -ENOMEM; } /* send a get connection info request */ retval = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, 0xc2, 0x0000, 0x0000, transfer_buffer, sizeof(*connection_info), 300); if (retval < 0) { dev_err(dev, "%s - error %d getting connection information\n", __FUNCTION__, retval); goto exit; } if (retval == sizeof(*connection_info)) { connection_info = (struct visor_connection_info *)transfer_buffer; num_ports = le16_to_cpu(connection_info->num_ports); for (i = 0; i < num_ports; ++i) { switch (connection_info->connections[i].port_function_id) { case VISOR_FUNCTION_GENERIC: string = "Generic"; break; case VISOR_FUNCTION_DEBUGGER: string = "Debugger"; break; case VISOR_FUNCTION_HOTSYNC: string = "HotSync"; break; case VISOR_FUNCTION_CONSOLE: string = "Console"; break; case VISOR_FUNCTION_REMOTE_FILE_SYS: string = "Remote File System"; break; default: string = "unknown"; break; } dev_info(dev, "%s: port %d, is for %s use\n", serial->type->description, connection_info->connections[i].port, string); } } /* * Handle devices that report invalid stuff here. */ if (num_ports == 0 || num_ports > 2) { dev_warn (dev, "%s: No valid connect info available\n", serial->type->description); num_ports = 2; } dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, num_ports); /* * save off our num_ports info so that we can use it in the * calc_num_ports callback */ usb_set_serial_data(serial, (void *)(long)num_ports); /* ask for the number of bytes available, but ignore the response as it is broken */ retval = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); if (retval < 0) dev_err(dev, "%s - error %d getting bytes available request\n", __FUNCTION__, retval); retval = 0;exit: kfree (transfer_buffer); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -