📄 mos7840.c
字号:
{ struct usb_device *dev = mcs->port->serial->dev; struct usb_ctrlrequest *dr = mcs->dr; unsigned char *buffer = mcs->ctrl_buf; int ret; dr->bRequestType = MCS_RD_RTYPE; dr->bRequest = MCS_RDREQ; dr->wValue = cpu_to_le16(Wval); //0; dr->wIndex = cpu_to_le16(reg); dr->wLength = cpu_to_le16(2); usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0), (unsigned char *)dr, buffer, 2, mos7840_control_callback, mcs); mcs->control_urb->transfer_buffer_length = 2; ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC); return ret;}/***************************************************************************** * mos7840_interrupt_callback * this is the callback function for when we have received data on the * interrupt endpoint. *****************************************************************************/static void mos7840_interrupt_callback(struct urb *urb){ int result; int length; struct moschip_port *mos7840_port; struct usb_serial *serial; __u16 Data; unsigned char *data; __u8 sp[5], st; int i, rv = 0; __u16 wval, wreg = 0; int status = urb->status; dbg("%s", " : Entering\n"); switch (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__, status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, status); goto exit; } length = urb->actual_length; data = urb->transfer_buffer; serial = (struct usb_serial *)urb->context; /* Moschip get 5 bytes * Byte 1 IIR Port 1 (port.number is 0) * Byte 2 IIR Port 2 (port.number is 1) * Byte 3 IIR Port 3 (port.number is 2) * Byte 4 IIR Port 4 (port.number is 3) * Byte 5 FIFO status for both */ if (length && length > 5) { dbg("%s \n", "Wrong data !!!"); return; } sp[0] = (__u8) data[0]; sp[1] = (__u8) data[1]; sp[2] = (__u8) data[2]; sp[3] = (__u8) data[3]; st = (__u8) data[4]; for (i = 0; i < serial->num_ports; i++) { mos7840_port = mos7840_get_port_private(serial->port[i]); wval = (((__u16) serial->port[i]->number - (__u16) (serial->minor)) + 1) << 8; if (mos7840_port->open) { if (sp[i] & 0x01) { dbg("SP%d No Interrupt !!!\n", i); } else { switch (sp[i] & 0x0f) { case SERIAL_IIR_RLS: dbg("Serial Port %d: Receiver status error or ", i); dbg("address bit detected in 9-bit mode\n"); mos7840_port->MsrLsr = 1; wreg = LINE_STATUS_REGISTER; break; case SERIAL_IIR_MS: dbg("Serial Port %d: Modem status change\n", i); mos7840_port->MsrLsr = 0; wreg = MODEM_STATUS_REGISTER; break; } spin_lock(&mos7840_port->pool_lock); if (!mos7840_port->zombie) { rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } else { spin_unlock(&mos7840_port->pool_lock); return; } spin_unlock(&mos7840_port->pool_lock); } } } if (!(rv < 0)) /* the completion handler for the control urb will resubmit */ return;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 int mos7840_port_paranoia_check(struct usb_serial_port *port, const char *function){ if (!port) { dbg("%s - port == NULL", function); return -1; } if (!port->serial) { dbg("%s - port->serial == NULL", function); return -1; } return 0;}/* Inline functions to check the sanity of a pointer that is passed to us */static int mos7840_serial_paranoia_check(struct usb_serial *serial, const char *function){ if (!serial) { dbg("%s - serial == NULL", function); return -1; } if (!serial->type) { dbg("%s - serial->type == NULL!", function); return -1; } return 0;}static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, const char *function){ /* if no port was specified, or it fails a paranoia check */ if (!port || mos7840_port_paranoia_check(port, function) || mos7840_serial_paranoia_check(port->serial, function)) { /* then say that we don't have a valid usb_serial thing, which will * end up genrating -ENODEV return values */ return NULL; } return port->serial;}/***************************************************************************** * mos7840_bulk_in_callback * this is the callback function for when we have received data on the * bulk in endpoint. *****************************************************************************/static void mos7840_bulk_in_callback(struct urb *urb){ int retval; unsigned char *data; struct usb_serial *serial; struct usb_serial_port *port; struct moschip_port *mos7840_port; struct tty_struct *tty; int status = urb->status; if (status) { dbg("nonzero read bulk status received: %d", status); return; } mos7840_port = (struct moschip_port *)urb->context; if (!mos7840_port) { dbg("%s", "NULL mos7840_port pointer \n"); return; } port = (struct usb_serial_port *)mos7840_port->port; if (mos7840_port_paranoia_check(port, __FUNCTION__)) { dbg("%s", "Port Paranoia failed \n"); return; } serial = mos7840_get_usb_serial(port, __FUNCTION__); if (!serial) { dbg("%s\n", "Bad serial pointer "); return; } dbg("%s\n", "Entering... \n"); data = urb->transfer_buffer; dbg("%s", "Entering ........... \n"); if (urb->actual_length) { tty = mos7840_port->port->tty; if (tty) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); dbg(" %s \n", data); tty_flip_buffer_push(tty); } mos7840_port->icount.rx += urb->actual_length; smp_wmb(); dbg("mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); } if (!mos7840_port->read_urb) { dbg("%s", "URB KILLED !!!\n"); return; } mos7840_port->read_urb->dev = serial->dev; retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); if (retval) { dbg(" usb_submit_urb(read bulk) failed, retval = %d", retval); }}/***************************************************************************** * mos7840_bulk_out_data_callback * this is the callback function for when we have finished sending serial data * on the bulk out endpoint. *****************************************************************************/static void mos7840_bulk_out_data_callback(struct urb *urb){ struct moschip_port *mos7840_port; struct tty_struct *tty; int status = urb->status; int i; mos7840_port = (struct moschip_port *)urb->context; spin_lock(&mos7840_port->pool_lock); for (i = 0; i < NUM_URBS; i++) { if (urb == mos7840_port->write_urb_pool[i]) { mos7840_port->busy[i] = 0; break; } } spin_unlock(&mos7840_port->pool_lock); if (status) { dbg("nonzero write bulk status received:%d\n", status); return; } if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) { dbg("%s", "Port Paranoia failed \n"); return; } dbg("%s \n", "Entering ........."); tty = mos7840_port->port->tty; if (tty && mos7840_port->open) tty_wakeup(tty);}/************************************************************************//* D R I V E R T T Y I N T E R F A C E F U N C T I O N S *//************************************************************************/#ifdef MCSSerialProbestatic int mos7840_serial_probe(struct usb_serial *serial, const struct usb_device_id *id){ /*need to implement the mode_reg reading and updating\ structures usb_serial_ device_type\ (i.e num_ports, num_bulkin,bulkout etc) */ /* Also we can update the changes attach */ return 1;}#endif/***************************************************************************** * mos7840_open * this function is called by the tty driver when a port is opened * If successful, we return 0 * Otherwise we return a negative error number. *****************************************************************************/static int mos7840_open(struct usb_serial_port *port, struct file *filp){ int response; int j; struct usb_serial *serial; struct urb *urb; __u16 Data; int status; struct moschip_port *mos7840_port; struct moschip_port *port0; if (mos7840_port_paranoia_check(port, __FUNCTION__)) { dbg("%s", "Port Paranoia failed \n"); return -ENODEV; } serial = port->serial; if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) { dbg("%s", "Serial Paranoia failed \n"); return -ENODEV; } mos7840_port = mos7840_get_port_private(port); port0 = mos7840_get_port_private(serial->port[0]); if (mos7840_port == NULL || port0 == NULL) return -ENODEV; usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); port0->open_ports++; /* Initialising the write urb pool */ for (j = 0; j < NUM_URBS; ++j) { urb = usb_alloc_urb(0, GFP_KERNEL); mos7840_port->write_urb_pool[j] = urb; if (urb == NULL) { err("No more urbs???"); continue; } urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); if (!urb->transfer_buffer) { usb_free_urb(urb); mos7840_port->write_urb_pool[j] = NULL; err("%s-out of memory for urb buffers.", __FUNCTION__); continue; } }/***************************************************************************** * Initialize MCS7840 -- Write Init values to corresponding Registers * * Register Index * 1 : IER * 2 : FCR * 3 : LCR * 4 : MCR * * 0x08 : SP1/2 Control Reg *****************************************************************************///NEED to check the following Block status = 0; Data = 0x0; status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); if (status < 0) { dbg("Reading Spreg failed\n"); return -1; } Data |= 0x80; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); if (status < 0) { dbg("writing Spreg failed\n"); return -1; } Data &= ~0x80; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); if (status < 0) { dbg("writing Spreg failed\n"); return -1; }//End of block to be checked status = 0; Data = 0x0; status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); if (status < 0) { dbg("Reading Controlreg failed\n"); return -1; } Data |= 0x08; //Driver done bit Data |= 0x20; //rx_disable status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); if (status < 0) { dbg("writing Controlreg failed\n"); return -1; } //do register settings here // Set all regs to the device default values. //////////////////////////////////// // First Disable all interrupts. //////////////////////////////////// Data = 0x00; status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); if (status < 0) { dbg("disableing interrupts failed\n"); return -1; } // Set FIFO_CONTROL_REGISTER to the default value Data = 0x00; status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); if (status < 0) { dbg("Writing FIFO_CONTROL_REGISTER failed\n"); return -1; } Data = 0xcf; status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); if (status < 0) { dbg("Writing FIFO_CONTROL_REGISTER failed\n"); return -1; } Data = 0x03; status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); mos7840_port->shadowLCR = Data; Data = 0x0b; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); mos7840_port->shadowMCR = Data; Data = 0x00; status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); mos7840_port->shadowLCR = Data; Data |= SERIAL_LCR_DLAB; //data latch enable in LCR 0x80 status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); Data = 0x0c; status = 0; status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); Data = 0x0; status = 0; status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); Data = 0x00; status = 0; status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); Data = Data & ~SERIAL_LCR_DLAB; status = 0; status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); mos7840_port->shadowLCR = Data; //clearing Bulkin and Bulkout Fifo Data = 0x0; status = 0; status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); Data = Data | 0x0c; status = 0; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -