static void ipaq_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; 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); bytes_in += urb->actual_length; } /* Continue trying to always read */ 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, ipaq_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); return; }
/*------------------------------------------------------------ 函数原型: void send_msg_to_user_space(PNDIS_NODE pnode, struct tty_struct * tty, int count) 描述: send_msg_to_user_space函数是在,当从USB底层成功读入NDIS消息 时,并且经过判别是WDS类型的消息,需要交给WDS进程或其他用户 进程进行处理的情况,调用tty核心的缓冲区流输入和流刷新函数 把WDS消息送入用户进程空间。 输入: PNDIS_NODE pnode 读入WDS消息的消息结点. struct tty_struct * tty 记录下的对应的用户进程打开的指向的 tty_struct的指针 int count 要刷新到用户进程空间的字节数。 输出: 输出到用户空间的WDS消息。 返回值: 无。 -------------------------------------------------------------*/ static void send_msg_to_user_space(PNDIS_NODE pnode, struct tty_struct * tty, int count) { int i = 0; if (NULL == tty) { printk("%s - tty maybe null.\n", __FUNCTION__); return; } /*printk("%s - send msg_len(0x%0x) to user space.\n", __FUNCTION__, count-SDU_START_POSITION);*/ /* < DTS2011011305021: gkf34687 2011-03-02 DEL>*/ tty_buffer_request_room(tty, count); for (i = 0; i < count; ++i) { #ifdef NDIS_MSG_PRINT_DBG printk("%02x ", *(MEG_ROW(pnode->row_num)+i)); #endif tty_insert_flip_char(tty, *(unsigned char *)(MEG_ROW(pnode->row_num)+i), TTY_NORMAL); } #ifdef NDIS_MSG_PRINT_DBG printk("\n "); #endif tty_flip_buffer_push(tty); #ifdef NDIS_MSG_PRINT_DBG printk("\n"); #endif }
static void vcons_rx_intr (NkPort* port) { unsigned int size; int i; int count = 0; while ((size = vcons_rxfifo_count(port))) { if (port->count == 0) { return; } if (port->stoprx) { break; } /* ask how many characters we can read */ size = tty_buffer_request_room(port->tty, size); if (size == 0) { return; } size = os_ctx->cops.read(port->id, port->buf, size); count += size; for (i = 0; i < size; i++) { tty_insert_flip_char(port->tty, port->buf[i], TTY_NORMAL); } } if (count > 0) { tty_schedule_flip(port->tty); } }
static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) { struct uart_port *port = &max->port; struct tty_struct *tty; int usable; /* If uart is not opened, just return */ if (!port->state) return; tty = port->state->port.tty; if (!tty) return; /* receive some char before the tty is opened */ while (len) { usable = tty_buffer_request_room(tty, len); if (usable) { tty_insert_flip_string(tty, str, usable); str += usable; port->icount.rx += usable; tty_flip_buffer_push(tty); } len -= usable; } }
int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) { int copied = 0; do { int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(tty, goal); /* If there is no space then tty->buf.tail may be NULL */ if(tty->buf.tail == 0) break; else{ struct tty_buffer *tb = tty->buf.tail; /* If there is no space then tb may be NULL */ if (unlikely(space == 0)) break; memcpy(tb->char_buf_ptr + tb->used, chars, space); memcpy(tb->flag_buf_ptr + tb->used, flags, space); tb->used += space; copied += space; chars += space; flags += space; /* There is a small chance that we need to split the data over several buffers. If this is the case we must loop */ } } while (unlikely(size > copied)); return copied; }
static void my_timer(unsigned long data) { /* TODO Auto-generated Function */ PINFO("my_uart_timer executing\n"); //------------------------------------------------------ char bytes[] = {'A'}; int data_size = 1; int i; //if (!tiny) // return; //tty = tiny->tty; //port = tty->port; /* send the data to the tty layer for users to read. This doesn't * actually push the data through unless tty->low_latency is set */ for (i = 0; i < data_size; ++i) { if (!tty_buffer_request_room(&devices[0].port, 1)) tty_flip_buffer_push(&devices[0].port); tty_insert_flip_char(&devices[0].port, bytes[i], TTY_NORMAL); } tty_flip_buffer_push(&devices[0].port); //------------------------------------------------------ my_uart_timer.expires = jiffies + MY_UART_DELAY_MS * HZ / 1000; add_timer(&my_uart_timer); }
static void tiny_timer(unsigned long timer_data) { struct tiny_serial *tiny = (struct tiny_serial *)timer_data; struct tty_struct *tty; struct tty_port *port; int i; char data[1] = {TINY_DATA_CHARACTER}; int data_size = 1; if (!tiny) return; tty = tiny->tty; port = tty->port; /* send the data to the tty layer for users to read. This doesn't * actually push the data through unless tty->low_latency is set */ for (i = 0; i < data_size; ++i) { if (!tty_buffer_request_room(port, 1)) tty_flip_buffer_push(port); tty_insert_flip_char(port, data[i], TTY_NORMAL); } tty_flip_buffer_push(port); /* resubmit the timer again */ tiny->timer->expires = jiffies + DELAY_TIME; add_timer(tiny->timer); }
static int gdm_tty_recv_complete(void *data, int len, int index, struct tty_dev *tty_dev, int complete) { struct gdm *gdm = tty_dev->gdm[index]; if (!GDM_TTY_READY(gdm)) { if (complete == RECV_PACKET_PROCESS_COMPLETE) gdm_tty_recv(gdm, gdm_tty_recv_complete); return TO_HOST_PORT_CLOSE; } if (data && len) { if (tty_buffer_request_room(&gdm->port, len) == len) { tty_insert_flip_string(&gdm->port, data, len); tty_flip_buffer_push(&gdm->port); } else { return TO_HOST_BUFFER_REQUEST_FAIL; } } if (complete == RECV_PACKET_PROCESS_COMPLETE) gdm_tty_recv(gdm, gdm_tty_recv_complete); return 0; }
/* Push data to tty layer and resubmit the bulk read URB */ static void flush_and_resubmit_read_urb (struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct urb *urb = port->read_urb; struct tty_struct *tty = port->tty; int result; /* Push data to tty */ if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ } /* Continue reading from device */ usb_fill_bulk_urb (port->read_urb, serial->dev, usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, ((serial->type->read_bulk_callback) ? serial->type->read_bulk_callback : usb_serial_generic_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); }
static void cyberjack_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; short todo; int result; int status = urb->status; dbg("%s - port %d", __func__, port->number); usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); if (status) { dbg("%s - nonzero read bulk status received: %d", __func__, status); return; } tty = tty_port_tty_get(&port->port); if (!tty) { dbg("%s - ignoring since device not open\n", __func__); return; } 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); } tty_kref_put(tty); spin_lock(&priv->lock); priv->rdtodo -= urb->actual_length; if (priv->rdtodo < 0) priv->rdtodo = 0; todo = priv->rdtodo; spin_unlock(&priv->lock); dbg("%s - rdtodo: %d", __func__, todo); if (todo ) { port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read " "urb, error %d\n", __func__, result); dbg("%s - usb_submit_urb(read urb)", __func__); } }
/*=========================================================================== METHOD: GobiReadBulkCallback (Free Method) DESCRIPTION: Read data from USB, push to TTY and user space PARAMETERS: pURB [ I ] - USB Request Block (urb) that called us RETURN VALUE: ===========================================================================*/ static void GobiReadBulkCallback( struct urb * pURB ) { struct usb_serial_port * pPort = pURB->context; struct tty_struct * pTTY = pPort->tty; int nResult; int nRoom = 0; unsigned int pipeEP; DBG( "port %d\n", pPort->number ); if (pURB->status != 0) { DBG( "nonzero read bulk status received: %d\n", pURB->status ); return; } usb_serial_debug_data( debug, &pPort->dev, __FUNCTION__, pURB->actual_length, pURB->transfer_buffer ); // We do no port throttling // Push data to tty layer and user space read function if (pTTY != 0 && pURB->actual_length) { nRoom = tty_buffer_request_room( pTTY, pURB->actual_length ); DBG( "room size %d %d\n", nRoom, 512 ); if (nRoom != 0) { tty_insert_flip_string( pTTY, pURB->transfer_buffer, nRoom ); tty_flip_buffer_push( pTTY ); } } pipeEP = usb_rcvbulkpipe( pPort->serial->dev, pPort->bulk_in_endpointAddress ); // For continuous reading usb_fill_bulk_urb( pPort->read_urb, pPort->serial->dev, pipeEP, pPort->read_urb->transfer_buffer, pPort->read_urb->transfer_buffer_length, GobiReadBulkCallback, pPort ); nResult = usb_submit_urb( pPort->read_urb, GFP_ATOMIC ); if (nResult != 0) { DBG( "failed resubmitting read urb, error %d\n", nResult ); } }
/* * byte channel receive interupt handler * * This ISR is called whenever data is available on a byte channel. */ static irqreturn_t ehv_bc_tty_rx_isr(int irq, void *data) { struct ehv_bc_data *bc = data; unsigned int rx_count, tx_count, len; int count; char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; int ret; /* Find out how much data needs to be read, and then ask the TTY layer * if it can handle that much. We want to ensure that every byte we * read from the byte channel will be accepted by the TTY layer. */ ev_byte_channel_poll(bc->handle, &rx_count, &tx_count); count = tty_buffer_request_room(&bc->port, rx_count); /* 'count' is the maximum amount of data the TTY layer can accept at * this time. However, during testing, I was never able to get 'count' * to be less than 'rx_count'. I'm not sure whether I'm calling it * correctly. */ while (count > 0) { len = min_t(unsigned int, count, sizeof(buffer)); /* Read some data from the byte channel. This function will * never return more than EV_BYTE_CHANNEL_MAX_BYTES bytes. */ ev_byte_channel_receive(bc->handle, &len, buffer); /* 'len' is now the amount of data that's been received. 'len' * can't be zero, and most likely it's equal to one. */ /* Pass the received data to the tty layer. */ ret = tty_insert_flip_string(&bc->port, buffer, len); /* 'ret' is the number of bytes that the TTY layer accepted. * If it's not equal to 'len', then it means the buffer is * full, which should never happen. If it does happen, we can * exit gracefully, but we drop the last 'len - ret' characters * that we read from the byte channel. */ if (ret != len) break; count -= len; } /* Tell the tty layer that we're done. */ tty_flip_buffer_push(&bc->port); return IRQ_HANDLED; }
int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size) { int space = tty_buffer_request_room(port, size); if (likely(space)) { struct tty_buffer *tb = port->buf.tail; *chars = tb->char_buf_ptr + tb->used; memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); tb->used += space; } return space; }
int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size) { int space = tty_buffer_request_room(tty, size); if (likely(space)) { struct tty_buffer *tb = tty->buf.tail; *chars = tb->char_buf_ptr + tb->used; *flags = tb->flag_buf_ptr + tb->used; tb->used += space; } return space; }
void gigaset_if_receive(struct cardstate *cs, unsigned char *buffer, size_t len) { unsigned long flags; struct tty_struct *tty; spin_lock_irqsave(&cs->lock, flags); if ((tty = cs->tty) == NULL) gig_dbg(DEBUG_ANY, "receive on closed device"); else { tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); tty_flip_buffer_push(tty); } spin_unlock_irqrestore(&cs->lock, flags); }
static void kobil_read_int_callback(struct urb *urb) { int result; struct usb_serial_port *port = urb->context; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; /* char *dbg_data; */ dbg("%s - port %d", __func__, port->number); if (status) { dbg("%s - port %d Read int status not zero: %d", __func__, port->number, status); return; } tty = tty_port_tty_get(&port->port); if (urb->actual_length) { /* BEGIN DEBUG */ /* dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); if (! dbg_data) { return; } for (i = 0; i < purb->actual_length; i++) { sprintf(dbg_data +3*i, "%02X ", data[i]); } dbg(" <-- %s", dbg_data); kfree(dbg_data); */ /* END DEBUG */ tty_buffer_request_room(tty, urb->actual_length); tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); } tty_kref_put(tty); /* someone sets the dev to 0 if the close method has been called */ port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result); }
/* Push data to tty layer and resubmit the bulk read URB */ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) { struct urb *urb = port->read_urb; struct tty_struct *tty = port->port.tty; int room; /* Push data to tty */ if (tty && urb->actual_length) { room = tty_buffer_request_room(tty, urb->actual_length); if (room) { tty_insert_flip_string(tty, urb->transfer_buffer, room); tty_flip_buffer_push(tty); } } resubmit_read_urb(port, GFP_ATOMIC); }
static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) { int result; struct usb_serial_port *port = (struct usb_serial_port *) purb->context; struct tty_struct *tty; unsigned char *data = purb->transfer_buffer; // char *dbg_data; dbg("%s - port %d", __FUNCTION__, port->number); if (purb->status) { dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status); return; } tty = port->tty; if (purb->actual_length) { // BEGIN DEBUG /* dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); if (! dbg_data) { return; } memset(dbg_data, 0, (3 * purb->actual_length + 10)); for (i = 0; i < purb->actual_length; i++) { sprintf(dbg_data +3*i, "%02X ", data[i]); } dbg(" <-- %s", dbg_data ); kfree(dbg_data); */ // END DEBUG tty_buffer_request_room(tty, purb->actual_length); tty_insert_flip_string(tty, data, purb->actual_length); tty_flip_buffer_push(tty); } // someone sets the dev to 0 if the close method has been called port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); }
static void navman_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; int status = urb->status; int result; 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", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); goto exit; } usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); tty = tty_port_tty_get(&port->port); 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); } tty_kref_put(tty); exit: result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __func__, result); }
int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) { int copied = 0; do { int space = tty_buffer_request_room(tty, size - copied); struct tty_buffer *tb = tty->buf.tail; /* If there is no space then tb may be NULL */ if (unlikely(space == 0)) break; memcpy(tb->char_buf_ptr + tb->used, chars, space); memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); tb->used += space; copied += space; chars += space; /* There is a small chance that we need to split the data over several buffers. If this is the case we must loop */ } while (unlikely(size > copied)); return copied; }
static void spi_tty_handle_data(void *context, u8 *buf, u32 count) { int cnt, crc, len; struct spi_tty_s *spi_tty; spi_msg_header header; SPI_IPC_INFO("%s, context=%p, buf=%p, count=%d\n", __func__, context, buf, count); if (!context || !buf || !count) { pr_err("%s - Invalid param!\n", __func__); return; } spi_ipc_buf_dump("rx header: ", buf, SPI_MSG_HEADER_LEN); spi_tty = (struct spi_tty_s *) context; spi_msg_get_header(buf, &header); crc = spi_msg_cal_crc(&header); // validate data if (header.type != 1 || header.len > SPI_MTU || header.fcs != crc) { pr_err("Invalid data receicved!\n"); return; } if (spi_tty->open_count > 0 && header.len > 0) { len = header.len; spi_ipc_buf_dump_ascii("rx data: ", buf+SPI_MSG_HEADER_LEN, (len>16?16:len)); SPI_IPC_INFO("insert data to tty\n"); buf += SPI_MSG_HEADER_LEN; do { cnt = tty_buffer_request_room(spi_tty->tty, len); if (cnt == 0) break; cnt = tty_insert_flip_string(spi_tty->tty, buf, cnt); tty_flip_buffer_push(spi_tty->tty); len -= cnt; buf += cnt; }while(len > 0); } }
static int receive_chars(struct uart_max3110 *max, unsigned short *str, int len) { struct uart_port *port = &max->port; struct tty_port *tport; char buf[M3110_RX_FIFO_DEPTH]; int r, w, usable; /* If uart is not opened, just return */ if (!port->state) return 0; tport = &port->state->port; for (r = 0, w = 0; r < len; r++) { if (str[r] & MAX3110_BREAK && uart_handle_break(port)) continue; if (str[r] & MAX3110_READ_DATA_AVAILABLE) { if (uart_handle_sysrq_char(port, str[r] & 0xff)) continue; buf[w++] = str[r] & 0xff; } } if (!w) return 0; for (r = 0; w; r += usable, w -= usable) { usable = tty_buffer_request_room(tport, w); if (usable) { tty_insert_flip_string(tport, buf + r, usable); port->icount.rx += usable; } } tty_flip_buffer_push(tport); return r; }
static void sierra_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", __func__, urb); endpoint = usb_pipeendpoint(urb->pipe); port = urb->context; if (status) { dev_dbg(&port->dev, "%s: nonzero status: %d on" " endpoint %02x.", __func__, status, endpoint); } else { tty = port->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 { dev_dbg(&port->dev, "%s: empty read urb" " received", __func__); } /* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN) { err = usb_submit_urb(urb, GFP_ATOMIC); if (err) dev_err(&port->dev, "resubmit read urb failed." "(%d)\n", err); } } return; }
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 acm_rx_tasklet(unsigned long _acm) { struct acm *acm = (void *)_acm; struct acm_rb *buf; struct tty_struct *tty = acm->tty; struct acm_ru *rcv; unsigned long flags; unsigned char throttled; dbg("Entering acm_rx_tasklet"); if (!ACM_READY(acm)) { dbg("acm_rx_tasklet: ACM not ready"); return; } spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (throttled) { dbg("acm_rx_tasklet: throttled"); return; } next_buffer: spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->filled_read_bufs)) { spin_unlock_irqrestore(&acm->read_lock, flags); goto urbs; } buf = list_entry(acm->filled_read_bufs.next, struct acm_rb, list); list_del(&buf->list); spin_unlock_irqrestore(&acm->read_lock, flags); dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); tty_buffer_request_room(tty, buf->size); spin_lock_irqsave(&acm->throttle_lock, flags); throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (!throttled) tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); if (throttled) { dbg("Throttling noticed"); spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->filled_read_bufs); spin_unlock_irqrestore(&acm->read_lock, flags); return; } spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->spare_read_bufs); spin_unlock_irqrestore(&acm->read_lock, flags); goto next_buffer; urbs: while (!list_empty(&acm->spare_read_bufs)) { spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->spare_read_urbs)) { acm->processing = 0; spin_unlock_irqrestore(&acm->read_lock, flags); return; } rcv = list_entry(acm->spare_read_urbs.next, struct acm_ru, list); list_del(&rcv->list); spin_unlock_irqrestore(&acm->read_lock, flags); buf = list_entry(acm->spare_read_bufs.next, struct acm_rb, list); list_del(&buf->list); rcv->buffer = buf; usb_fill_bulk_urb(rcv->urb, acm->dev, acm->rx_endpoint, buf->base, acm->readsize, acm_read_bulk, rcv); rcv->urb->transfer_dma = buf->dma; rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* This shouldn't kill the driver as unsuccessful URBs are returned to the free-urbs-pool and resubmited ASAP */ spin_lock_irqsave(&acm->read_lock, flags); if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { list_add(&buf->list, &acm->spare_read_bufs); list_add(&rcv->list, &acm->spare_read_urbs); acm->processing = 0; spin_unlock_irqrestore(&acm->read_lock, flags); return; } else { spin_unlock_irqrestore(&acm->read_lock, flags); dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf); } } spin_lock_irqsave(&acm->read_lock, flags); acm->processing = 0; spin_unlock_irqrestore(&acm->read_lock, flags); }
/* * Receive characters */ static void cpm_uart_int_rx(struct uart_port *port) { int i; unsigned char ch, *cp; struct tty_struct *tty = port->info->tty; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; volatile cbd_t *bdp; u16 status; unsigned int flg; pr_debug("CPM uart[%d]:RX INT\n", port->line); /* Just loop through the closed BDs and copy the characters into * the buffer. */ bdp = pinfo->rx_cur; for (;;) { /* get status */ status = bdp->cbd_sc; /* If this one is empty, return happy */ if (status & BD_SC_EMPTY) break; /* get number of characters, and check spce in flip-buffer */ i = bdp->cbd_datlen; /* If we have not enough room in tty flip buffer, then we try * later, which will be the next rx-interrupt or a timeout */ if(tty_buffer_request_room(tty, i) < i) { printk(KERN_WARNING "No room in flip buffer\n"); return; } /* get pointer */ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); /* loop through the buffer */ while (i-- > 0) { ch = *cp++; port->icount.rx++; flg = TTY_NORMAL; if (status & (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV)) goto handle_error; if (uart_handle_sysrq_char(port, ch)) continue; error_return: tty_insert_flip_char(tty, ch, flg); } /* End while (i--) */ /* This BD is ready to be used again. Clear status. get next */ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID); bdp->cbd_sc |= BD_SC_EMPTY; if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->rx_bd_base; else bdp++; } /* End for (;;) */ /* Write back buffer pointer */ pinfo->rx_cur = (volatile cbd_t *) bdp; /* activate BH processing */ tty_flip_buffer_push(tty); return; /* Error processing */ handle_error: /* Statistics */ if (status & BD_SC_BR) port->icount.brk++; if (status & BD_SC_PR) port->icount.parity++; if (status & BD_SC_FR) port->icount.frame++; if (status & BD_SC_OV) port->icount.overrun++; /* Mask out ignored conditions */ status &= port->read_status_mask; /* Handle the remaining ones */ if (status & BD_SC_BR) flg = TTY_BREAK; else if (status & BD_SC_PR) flg = TTY_PARITY; else if (status & BD_SC_FR) flg = TTY_FRAME; /* overrun does not affect the current character ! */ if (status & BD_SC_OV) { ch = 0; flg = TTY_OVERRUN; /* We skip this buffer */ /* CHECK: Is really nothing senseful there */ /* ASSUMPTION: it contains nothing valid */ i = 0; } #ifdef SUPPORT_SYSRQ port->sysrq = 0; #endif goto error_return; }
static void opticon_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; unsigned char *data = urb->transfer_buffer; struct usb_serial_port *port = priv->port; int status = urb->status; struct tty_struct *tty; int result; int available_room = 0; int data_length; dbg("%s - port %d", __func__, port->number); switch (status) { case 0: break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: dbg("%s - urb shutting down with status: %d", __func__, status); return; default: dbg("%s - nonzero urb status received: %d", __func__, status); goto exit; } usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); if (urb->actual_length > 2) { data_length = urb->actual_length - 2; if ((data[0] == 0x00) && (data[1] == 0x00)) { tty = tty_port_tty_get(&port->port); if (tty) { available_room = tty_buffer_request_room(tty, data_length); if (available_room) { tty_insert_flip_string(tty, data, available_room); tty_flip_buffer_push(tty); } tty_kref_put(tty); } } else { if ((data[0] == 0x00) && (data[1] == 0x01)) { if (data[2] == 0x00) priv->rts = false; else priv->rts = true; } else { dev_dbg(&priv->udev->dev, "Unknown data packet received from the device:" " %2x %2x\n", data[0], data[1]); } } } else { dev_dbg(&priv->udev->dev, "Improper ammount of data received from the device, " "%d bytes", urb->actual_length); } exit: spin_lock(&priv->lock); if (!priv->throttled) { usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, usb_rcvbulkpipe(priv->udev, priv->bulk_address), priv->bulk_in_buffer, priv->buffer_size, opticon_bulk_callback, priv); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); } else priv->actually_throttled = true; spin_unlock(&priv->lock); }
static void acm_rx_tasklet(unsigned long _acm) { struct acm *acm = (void *)_acm; struct acm_rb *buf; struct tty_struct *tty = acm->tty; struct acm_ru *rcv; //unsigned long flags; int i = 0; dbg("Entering acm_rx_tasklet"); if (!ACM_READY(acm) || acm->throttle) return; next_buffer: spin_lock(&acm->read_lock); if (list_empty(&acm->filled_read_bufs)) { spin_unlock(&acm->read_lock); goto urbs; } buf = list_entry(acm->filled_read_bufs.next, struct acm_rb, list); list_del(&buf->list); spin_unlock(&acm->read_lock); dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size); tty_buffer_request_room(tty, buf->size); if (!acm->throttle) tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); spin_lock(&acm->throttle_lock); if (acm->throttle) { dbg("Throtteling noticed"); memmove(buf->base, buf->base + i, buf->size - i); buf->size -= i; spin_unlock(&acm->throttle_lock); spin_lock(&acm->read_lock); list_add(&buf->list, &acm->filled_read_bufs); spin_unlock(&acm->read_lock); return; } spin_unlock(&acm->throttle_lock); spin_lock(&acm->read_lock); list_add(&buf->list, &acm->spare_read_bufs); spin_unlock(&acm->read_lock); goto next_buffer; urbs: while (!list_empty(&acm->spare_read_bufs)) { spin_lock(&acm->read_lock); if (list_empty(&acm->spare_read_urbs)) { spin_unlock(&acm->read_lock); return; } rcv = list_entry(acm->spare_read_urbs.next, struct acm_ru, list); list_del(&rcv->list); spin_unlock(&acm->read_lock); buf = list_entry(acm->spare_read_bufs.next, struct acm_rb, list); list_del(&buf->list); rcv->buffer = buf; usb_fill_bulk_urb(rcv->urb, acm->dev, acm->rx_endpoint, buf->base, acm->readsize, acm_read_bulk, rcv); rcv->urb->transfer_dma = buf->dma; rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf); /* This shouldn't kill the driver as unsuccessful URBs are returned to the free-urbs-pool and resubmited ASAP */ if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { list_add(&buf->list, &acm->spare_read_bufs); spin_lock(&acm->read_lock); list_add(&rcv->list, &acm->spare_read_urbs); spin_unlock(&acm->read_lock); return; } } }
/* bulk read call back function. check the status of the urb. if transfer * failed return. then update the status and the tty send data to tty subsys. * submit urb again. */ static void spcp8x5_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct spcp8x5_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; int i; int result; u8 status = 0; char tty_flag; dev_dbg(&port->dev, "start, urb->status = %d, " "urb->actual_length = %d\n,", urb->status, urb->actual_length); /* check the urb status */ if (urb->status) { if (!port->open_count) return; if (urb->status == -EPROTO) { /* spcp8x5 mysteriously fails with -EPROTO */ /* reschedule the read */ urb->status = 0; urb->dev = port->serial->dev; result = usb_submit_urb(urb , GFP_ATOMIC); if (result) dev_dbg(&port->dev, "failed submitting read urb %d\n", result); return; } dev_dbg(&port->dev, "unable to handle the error, exiting.\n"); return; } /* get tty_flag from status */ tty_flag = TTY_NORMAL; spin_lock_irqsave(&priv->lock, flags); status = priv->line_status; priv->line_status &= ~UART_STATE_TRANSIENT_MASK; spin_unlock_irqrestore(&priv->lock, flags); /* wake up the wait for termios */ wake_up_interruptible(&priv->delta_msr_wait); /* break takes precedence over parity, which takes precedence over * framing errors */ if (status & UART_BREAK_ERROR) tty_flag = TTY_BREAK; else if (status & UART_PARITY_ERROR) tty_flag = TTY_PARITY; else if (status & UART_FRAME_ERROR) tty_flag = TTY_FRAME; dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); tty = port->tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); for (i = 0; i < urb->actual_length; ++i) tty_insert_flip_char(tty, data[i], tty_flag); tty_flip_buffer_push(tty); } /* Schedule the next read _if_ we are still open */ if (port->open_count) { urb->dev = port->serial->dev; result = usb_submit_urb(urb , GFP_ATOMIC); if (result) dev_dbg(&port->dev, "failed submitting read urb %d\n", result); } return; }
static void modem_rx_tasklet(unsigned long _modem_port) { struct modem_port *modem_port_ptr = (void *)_modem_port; struct ap_rb *buf; struct tty_struct *tty; struct usb_serial_port *port; struct ap_ru *rcv; unsigned long flags; unsigned char throttled; int ret = -1; if (!modem_port_ptr) return; port = modem_port_ptr->port; if (!port) return; tty = port->port.tty; if (!tty) return; spin_lock_irqsave(&modem_port_ptr->port->lock, flags); throttled = modem_port_ptr->port->throttle_req; spin_unlock_irqrestore(&modem_port_ptr->port->lock, flags); if (throttled) { dev_err(&port->dev, "%s: throttled.\n", __func__); return; } next_buffer: spin_lock_irqsave(&modem_port_ptr->read_lock, flags); if (list_empty(&modem_port_ptr->filled_read_bufs)) { spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); goto urbs; } buf = list_entry(modem_port_ptr->filled_read_bufs.next, struct ap_rb, list); list_del(&buf->list); spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); tty_buffer_request_room(tty, buf->size); spin_lock_irqsave(&modem_port_ptr->port->lock, flags); throttled = modem_port_ptr->port->throttle_req; spin_unlock_irqrestore(&modem_port_ptr->port->lock, flags); if (!throttled) tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); if (throttled) { dev_err(&port->dev, "%s: Throttling noticed.\n", __func__); spin_lock_irqsave(&modem_port_ptr->read_lock, flags); list_add(&buf->list, &modem_port_ptr->filled_read_bufs); spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); return; } spin_lock_irqsave(&modem_port_ptr->read_lock, flags); list_add_tail(&buf->list, &modem_port_ptr->spare_read_bufs); spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); goto next_buffer; urbs: while (1) { spin_lock_irqsave(&modem_port_ptr->read_lock, flags); if (list_empty(&modem_port_ptr->spare_read_bufs)) { spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); break; } if (list_empty(&modem_port_ptr->spare_read_urbs)) { modem_port_ptr->processing = 0; spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); if (cdma_modem_debug) dev_info(&port->dev, "%s: no urb to create.\n", __func__); return; } rcv = list_entry(modem_port_ptr->spare_read_urbs.next, struct ap_ru, list); list_del(&rcv->list); buf = list_entry(modem_port_ptr->spare_read_bufs.next, struct ap_rb, list); list_del(&buf->list); spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); rcv->buffer = buf; usb_fill_bulk_urb(rcv->urb, modem_port_ptr->port->serial->dev, modem_port_ptr->rx_endpoint, buf->base, modem_port_ptr->readsize, modem_read_bulk_callback, rcv); rcv->urb->transfer_dma = buf->dma; rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; spin_lock_irqsave(&modem_port_ptr->read_lock, flags); if ((modem_port_ptr->susp_count > 0) || (ret = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) { if (cdma_modem_debug) dev_info(&port->dev, "%s():susp_count=%d ret=%d\n", __func__, modem_port_ptr->susp_count, ret); list_add_tail(&buf->list, &modem_port_ptr->spare_read_bufs); list_add_tail(&rcv->list, &modem_port_ptr->spare_read_urbs); modem_port_ptr->processing = 0; dev_err(&port->dev, "%s: submit bulk in urb failed.\n", __func__); spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); return; } else { spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); } } spin_lock_irqsave(&modem_port_ptr->read_lock, flags); modem_port_ptr->processing = 0; spin_unlock_irqrestore(&modem_port_ptr->read_lock, flags); }