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); } }
void spi_tty_write_worker(struct work_struct *work) { int c; int crc; unsigned long flags; unsigned long start_t = 0; spi_msg_header header; struct spi_tty_s *spi_tty = container_of(work, struct spi_tty_s, write_work); start_t = jiffies; SPI_IPC_INFO("%s Enter\n", __func__); mutex_lock(&(spi_tty->work_lock)); spin_lock_irqsave(&(spi_tty->port_lock), flags); while( ((c = spi_tty_buf_data_avail(spi_tty->write_buf)) || (spi_tty->tx_null)) && (!spi_tty->throttle) && (!spi_tty->spi_slave_dev->peer_is_dead)) { if (spi_tty->tx_null) spi_tty->tx_null = 0; // initiate spi_big_trans memset(spi_big_trans.tx_buf, 0x0, SPI_TRANSACTION_LEN*2); spi_big_msg.actual_length = 0; c = MIN(c, SPI_MTU); spi_tty_buf_get(spi_tty->write_buf, spi_big_trans.tx_buf+SPI_MSG_HEADER_LEN, c); if (spi_tty->tty && spi_tty->open_count) tty_wakeup(spi_tty->tty); spin_unlock_irqrestore(&(spi_tty->port_lock), flags); header.type = 1; header.len = c; header.dtr = spi_tty->dtr; crc = spi_msg_cal_crc(&header); header.fcs = crc; spi_msg_set_header(spi_big_trans.tx_buf, &header); spi_big_trans.len = c + SPI_MSG_HEADER_LEN; spi_ipc_buf_dump("tx header: ", spi_big_trans.tx_buf, SPI_MSG_HEADER_LEN); spi_ipc_buf_dump_ascii("tx data: ", spi_big_trans.tx_buf + SPI_MSG_HEADER_LEN, (c>16?16:c)); spi_slave_sync(mdm6600_spi_dev.spi, &spi_big_msg); if (spi_big_msg.actual_length == SPI_TRANSACTION_LEN) { tx_count++; tx_size += spi_big_trans.len - SPI_MSG_HEADER_LEN; spi_tty_handle_data(spi_tty, spi_big_trans.rx_buf, SPI_TRANSACTION_LEN); }else { pr_err("%s: spi_slave_sync() failed to transfer data!\n", __func__); } // wake up writes wait on queue wake_up_interruptible(&spi_tty->write_wait); spin_lock_irqsave(&(spi_tty->port_lock), flags); } spin_unlock_irqrestore(&(spi_tty->port_lock), flags); mutex_unlock(&(spi_tty->work_lock)); SPI_IPC_INFO("%s Exit\n", __func__); tx_time += jiffies_to_msecs(jiffies - start_t); }
static void spi_tty_write_worker(struct work_struct *work) { int c; int crc; unsigned long flags; unsigned long start_t = 0; spi_msg_header header; struct spi_tty_s *spi_tty = container_of(work, struct spi_tty_s, write_work); start_t = jiffies; SPI_IPC_INFO("%s\n", __func__); mutex_lock(&(spi_tty->work_lock)); spin_lock_irqsave(&(spi_tty->port_lock), flags); while(((c = spi_tty_buf_data_avail(spi_tty->write_buf)) || (spi_tty->tx_null)) && (!spi_tty->throttle) && (!(spi_tty_dev && spi_tty_dev->peer_is_dead))) { SPI_IPC_INFO("%s: %d outgoing bytes\n", __func__, c); if (spi_tty->tx_null) spi_tty->tx_null = 0; // initiate spi_big_trans memset((char*)spi_big_trans.tx_buf, 0x0, SPI_TRANSACTION_LEN * 2); spi_big_msg.actual_length = 0; c = MIN(c, SPI_MTU); spi_tty_buf_get(spi_tty->write_buf, (char*)spi_big_trans.tx_buf + SPI_MSG_HEADER_LEN, c); if (spi_tty->tty && spi_tty->open_count) tty_wakeup(spi_tty->tty); spin_unlock_irqrestore(&(spi_tty->port_lock), flags); header.type = 1; header.len = c; header.dtr = spi_tty->dtr; crc = spi_msg_cal_crc(&header); header.fcs = crc; spi_msg_set_header((u8*)spi_big_trans.tx_buf, &header); #if SPI_TTY_FORCE_FULL_TRANSACTION spi_big_trans.len = SPI_TRANSACTION_LEN; #else spi_big_trans.len = c + SPI_MSG_HEADER_LEN; #endif spi_big_trans.speed_hz = SPI_SPEED_HZ; spi_big_trans.bits_per_word = 32; spi_ipc_buf_dump("tx header: ", spi_big_trans.tx_buf, SPI_MSG_HEADER_LEN); spi_ipc_buf_dump_ascii("tx data: ", spi_big_trans.tx_buf + SPI_MSG_HEADER_LEN, (c>16?16:c)); if (spi_tty_dev) spi_sync(spi_tty_dev->spi, &spi_big_msg); else pr_warning("%s: dropping data: no spi device " "registered", __func__); if (spi_big_msg.actual_length == SPI_TRANSACTION_LEN) { tx_count++; tx_size += spi_big_trans.len - SPI_MSG_HEADER_LEN; spi_tty_handle_data(spi_tty, spi_big_trans.rx_buf, SPI_TRANSACTION_LEN); }else { pr_err("%s: spi data transfer failed\n", __func__); } // wake up writes wait on queue wake_up_interruptible(&spi_tty->write_wait); spin_lock_irqsave(&(spi_tty->port_lock), flags); } spin_unlock_irqrestore(&(spi_tty->port_lock), flags); mutex_unlock(&(spi_tty->work_lock)); SPI_IPC_INFO("%s: done\n", __func__); tx_time += jiffies_to_msecs(jiffies - start_t); }