📄 usbserial.c
字号:
cause the "hotplug" program to pull in whatever module is necessary
via modprobe, and modprobe will load usbserial because the serial
drivers depend on it.
*/
static int serial_refcount;
static struct tty_driver serial_tty_driver;
static struct tty_struct *serial_tty[SERIAL_TTY_MINORS];
static struct termios *serial_termios[SERIAL_TTY_MINORS];
static struct termios *serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
LIST_HEAD(usb_serial_driver_list);
static struct usb_serial *get_serial_by_minor(int minor)
{
return serial_table[minor];
}
static struct usb_serial *get_free_serial(int num_ports, int *minor)
{
struct usb_serial *serial = NULL;
int i, j;
int good_spot;
dbg(__FUNCTION__ " %d", num_ports);
*minor = 0;
for(i = 0; i < SERIAL_TTY_MINORS; ++i) {
if(serial_table[i])
continue;
good_spot = 1;
for(j = 1; j <= num_ports - 1; ++j)
if(serial_table[i + j])
good_spot = 0;
if(good_spot == 0)
continue;
if(!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) {
err(__FUNCTION__ " - Out of memory");
return NULL;
}
memset(serial, 0, sizeof(struct usb_serial));
serial->magic = USB_SERIAL_MAGIC;
serial_table[i] = serial;
*minor = i;
dbg(__FUNCTION__ " - minor base = %d", *minor);
for(i = *minor + 1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
serial_table[i] = serial;
return serial;
}
return NULL;
}
static void return_serial(struct usb_serial *serial)
{
int i;
dbg(__FUNCTION__);
if(serial == NULL)
return;
for(i = 0; i < serial->num_ports; ++i) {
serial_table[serial->minor + i] = NULL;
}
return;
}
#ifdef USES_EZUSB_FUNCTIONS
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
int ezusb_writememory(struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
{
int result;
unsigned char *transfer_buffer = kmalloc(length, GFP_KERNEL);
// dbg("ezusb_writememory %x, %d", address, length);
if(!transfer_buffer) {
err(__FUNCTION__ " - kmalloc(%d) failed.", length);
return -ENOMEM;
}
memcpy(transfer_buffer, data, length);
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer,
length, 300);
kfree(transfer_buffer);
return result;
}
int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
{
int response;
dbg(__FUNCTION__ " - %d", reset_bit);
response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if(response < 0) {
err(__FUNCTION__ "- %d failed", reset_bit);
}
return response;
}
#endif /* USES_EZUSB_FUNCTIONS */
/*****************************************************************************
* Driver tty interface functions
*****************************************************************************/
static int serial_open(struct tty_struct *tty, struct file *filp)
{
struct usb_serial *serial;
struct usb_serial_port *port;
int portNumber;
dbg(__FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
/* get the serial object associated with this tty pointer */
serial = get_serial_by_minor(MINOR(tty->device));
if(serial_paranoia_check(serial, __FUNCTION__)) {
return -ENODEV;
}
MOD_INC_USE_COUNT;
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor;
port = &serial->port[portNumber];
tty->driver_data = port;
port->tty = tty;
/* pass on to the driver specific version of this function if it is available */
if(serial->type->open) {
return(serial->type->open(port, filp));
}
else {
return(generic_open(port, filp));
}
}
static void serial_close(struct tty_struct *tty, struct file *filp)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not opened");
return;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->close) {
serial->type->close(port, filp);
}
else {
generic_close(port, filp);
}
MOD_DEC_USE_COUNT;
}
static int serial_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return -ENODEV;
}
dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
if(!port->active) {
dbg(__FUNCTION__ " - port not opened");
return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->write) {
return(serial->type->write(port, from_user, buf, count));
}
else {
return(generic_write(port, from_user, buf, count));
}
}
static int serial_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return -ENODEV;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->write_room) {
return(serial->type->write_room(port));
}
else {
return(generic_write_room(port));
}
}
static int serial_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return -ENODEV;
}
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->chars_in_buffer) {
return(serial->type->chars_in_buffer(port));
}
else {
return(generic_chars_in_buffer(port));
}
}
static void serial_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return;
}
/* pass on to the driver specific version of this function */
if(serial->type->throttle) {
serial->type->throttle(port);
}
return;
}
static void serial_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return;
}
/* pass on to the driver specific version of this function */
if(serial->type->unthrottle) {
serial->type->unthrottle(port);
}
return;
}
static int serial_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return -ENODEV;
}
dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return -ENODEV;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->ioctl) {
return(serial->type->ioctl(port, file, cmd, arg));
}
else {
return -ENOIOCTLCMD;
}
}
static void serial_set_termios(struct tty_struct *tty, struct termios *old)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return;
}
/* pass on to the driver specific version of this function if it is available */
if(serial->type->set_termios) {
serial->type->set_termios(port, old);
}
return;
}
static void serial_break(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = (struct usb_serial_port *)tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
if(!serial) {
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
if(!port->active) {
dbg(__FUNCTION__ " - port not open");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -