コード例 #1
0
ファイル: n_r3964.c プロジェクト: ManiacTwister/linux-hnd
static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg)
{
	struct r3964_client_info *pClient;
	struct r3964_client_info **ppClient;
	struct r3964_message *pMsg;

	if ((arg & R3964_SIG_ALL) == 0) {
		/* Remove client from client list */
		for (ppClient = &pInfo->firstClient; *ppClient;
		     ppClient = &(*ppClient)->next) {
			pClient = *ppClient;

			if (pClient->pid == pid) {
				TRACE_PS("removing client %d from client list",
					 pid_nr(pid));
				*ppClient = pClient->next;
				while (pClient->msg_count) {
					pMsg = remove_msg(pInfo, pClient);
					if (pMsg) {
						kfree(pMsg);
						TRACE_M("enable_signals - msg "
							"kfree %p", pMsg);
					}
				}
				put_pid(pClient->pid);
				kfree(pClient);
				TRACE_M("enable_signals - kfree %p", pClient);
				return 0;
			}
		}
		return -EINVAL;
	} else {
		pClient = findClient(pInfo, pid);
		if (pClient) {
			/* update signal options */
			pClient->sig_flags = arg;
		} else {
			/* add client to client list */
			pClient = kmalloc(sizeof(struct r3964_client_info),
					GFP_KERNEL);
			TRACE_M("enable_signals - kmalloc %p", pClient);
			if (pClient == NULL)
				return -ENOMEM;

			TRACE_PS("add client %d to client list", pid_nr(pid));
			spin_lock_init(&pClient->lock);
			pClient->sig_flags = arg;
			pClient->pid = get_pid(pid);
			pClient->next = pInfo->firstClient;
			pClient->first_msg = NULL;
			pClient->last_msg = NULL;
			pClient->next_block_to_read = NULL;
			pClient->msg_count = 0;
			pInfo->firstClient = pClient;
		}
	}

	return 0;
}
コード例 #2
0
ファイル: n_r3964.c プロジェクト: archith/camera_project
static void trigger_transmit(struct r3964_info *pInfo)
{
   unsigned long flags;
   

   save_flags(flags);
   cli();

   if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))
   {
      pInfo->state = R3964_TX_REQUEST;
      pInfo->count_down = R3964_TO_QVZ;
      pInfo->nRetry=0;
      pInfo->flags &= ~R3964_ERROR;
      
      restore_flags(flags);

      TRACE_PS("trigger_transmit - sent STX");

      put_char(pInfo, STX);
      flush(pInfo);

      pInfo->bcc = 0;
   }
   else
   {
      restore_flags(flags);
   }
}
コード例 #3
0
ファイル: n_r3964.c プロジェクト: archith/camera_project
static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
			  unsigned char *buf, size_t nr)
{
   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
   struct r3964_client_info *pClient;
   struct r3964_message *pMsg;
   struct r3964_client_message theMsg;
   DECLARE_WAITQUEUE (wait, current);
   
   int pid = current->pid;
   int count;
   
   TRACE_L("read()");
 
   pClient=findClient(pInfo, pid);
   if(pClient)
   {
      pMsg = remove_msg(pInfo, pClient);
      if(pMsg==NULL)
      {
		 /* no messages available. */
         if (file->f_flags & O_NONBLOCK)
		 {
            return -EAGAIN;
		 }
         /* block until there is a message: */
         add_wait_queue(&pInfo->read_wait, &wait);
repeat:
         current->state = TASK_INTERRUPTIBLE;
         pMsg = remove_msg(pInfo, pClient);
	 if (!pMsg && !signal_pending(current))
		 {
            schedule();
            goto repeat;
         }
         current->state = TASK_RUNNING;
         remove_wait_queue(&pInfo->read_wait, &wait);
      }
      
      /* If we still haven't got a message, we must have been signalled */

      if (!pMsg) return -EINTR;

      /* deliver msg to client process: */
      theMsg.msg_id = pMsg->msg_id;
      theMsg.arg    = pMsg->arg;
      theMsg.error_code = pMsg->error_code;
      count = sizeof(struct r3964_client_message);

      kfree(pMsg);
      TRACE_M("r3964_read - msg kfree %x",(int)pMsg);

      if (copy_to_user(buf,&theMsg, count))
	return -EFAULT;

      TRACE_PS("read - return %d", count);
      return count;
   }
   return -EPERM;
}
static void trigger_transmit(struct r3964_info *pInfo)
{
   unsigned long flags;
   

   spin_lock_irqsave(&pInfo->lock, flags);

   if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))
   {
      pInfo->state = R3964_TX_REQUEST;
      pInfo->nRetry=0;
      pInfo->flags &= ~R3964_ERROR;
      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);

      spin_unlock_irqrestore(&pInfo->lock, flags);

      TRACE_PS("trigger_transmit - sent STX");

      put_char(pInfo, STX);
      flush(pInfo);

      pInfo->bcc = 0;
   }
   else
   {
      spin_unlock_irqrestore(&pInfo->lock, flags);
   }
}
コード例 #5
0
ファイル: n_r3964.c プロジェクト: aywq2008/omniplay
static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
			  unsigned char __user * buf, size_t nr)
{
	struct r3964_info *pInfo = tty->disc_data;
	struct r3964_client_info *pClient;
	struct r3964_message *pMsg;
	struct r3964_client_message theMsg;
	int ret;

	TRACE_L("read()");

	tty_lock();

	pClient = findClient(pInfo, task_pid(current));
	if (pClient) {
		pMsg = remove_msg(pInfo, pClient);
		if (pMsg == NULL) {
			/* no messages available. */
			if (file->f_flags & O_NONBLOCK) {
				ret = -EAGAIN;
				goto unlock;
			}
			/* block until there is a message: */
			wait_event_interruptible_tty(pInfo->read_wait,
					(pMsg = remove_msg(pInfo, pClient)));
		}

		/* If we still haven't got a message, we must have been signalled */

		if (!pMsg) {
			ret = -EINTR;
			goto unlock;
		}

		/* deliver msg to client process: */
		theMsg.msg_id = pMsg->msg_id;
		theMsg.arg = pMsg->arg;
		theMsg.error_code = pMsg->error_code;
		ret = sizeof(struct r3964_client_message);

		kfree(pMsg);
		TRACE_M("r3964_read - msg kfree %p", pMsg);

		if (copy_to_user(buf, &theMsg, ret)) {
			ret = -EFAULT;
			goto unlock;
		}

		TRACE_PS("read - return %d", ret);
		goto unlock;
	}
	ret = -EPERM;
unlock:
	tty_unlock();
	return ret;
}
コード例 #6
0
ファイル: n_r3964.c プロジェクト: ManiacTwister/linux-hnd
static void dump_block(const unsigned char *block, unsigned int length)
{
	unsigned int i, j;
	char linebuf[16 * 3 + 1];

	for (i = 0; i < length; i += 16) {
		for (j = 0; (j < 16) && (j + i < length); j++) {
			sprintf(linebuf + 3 * j, "%02x ", block[i + j]);
		}
		linebuf[3 * j] = '\0';
		TRACE_PS("%s", linebuf);
	}
}
コード例 #7
0
ファイル: n_r3964.c プロジェクト: ManiacTwister/linux-hnd
static void remove_client_block(struct r3964_info *pInfo,
				struct r3964_client_info *pClient)
{
	struct r3964_block_header *block;

	TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid));

	block = pClient->next_block_to_read;
	if (block) {
		block->locks--;
		if (block->locks == 0) {
			remove_from_rx_queue(pInfo, block);
		}
	}
	pClient->next_block_to_read = NULL;
}
コード例 #8
0
ファイル: n_r3964.c プロジェクト: archith/camera_project
static void transmit_block(struct r3964_info *pInfo)
{
   struct tty_struct *tty = pInfo->tty;
   struct r3964_block_header *pBlock = pInfo->tx_first;
   int room=0;

   if((tty==NULL) || (pBlock==NULL))
   {
      return;
   }

   if(tty->driver.write_room)
      room=tty->driver.write_room(tty);

   TRACE_PS("transmit_block %x, room %d, length %d", 
          (int)pBlock, room, pBlock->length);
   
   while(pInfo->tx_position < pBlock->length)
   {
      if(room<2)
         break;
 
      if(pBlock->data[pInfo->tx_position]==DLE)
      {
         /* send additional DLE char: */
         put_char(pInfo, DLE);
      }
      put_char(pInfo, pBlock->data[pInfo->tx_position++]);
      
      room--;
   }

   if((pInfo->tx_position == pBlock->length) && (room>=3))
   {
      put_char(pInfo, DLE);
      put_char(pInfo, ETX);
      if(pInfo->flags & R3964_BCC)
      {
         put_char(pInfo, pInfo->bcc);
      }
      pInfo->state = R3964_WAIT_FOR_TX_ACK;
      pInfo->count_down = R3964_TO_QVZ;
   }
   flush(pInfo);
}
コード例 #9
0
static void transmit_block(struct r3964_info *pInfo)
{
	struct tty_struct *tty = pInfo->tty;
	struct r3964_block_header *pBlock = pInfo->tx_first;
	int room = 0;

	if (tty == NULL || pBlock == NULL) {
		return;
	}

	room = tty_write_room(tty);

	TRACE_PS("transmit_block %p, room %d, length %d",
		 pBlock, room, pBlock->length);

	while (pInfo->tx_position < pBlock->length) {
		if (room < 2)
			break;

		if (pBlock->data[pInfo->tx_position] == DLE) {
			
			put_char(pInfo, DLE);
		}
		put_char(pInfo, pBlock->data[pInfo->tx_position++]);

		room--;
	}

	if ((pInfo->tx_position == pBlock->length) && (room >= 3)) {
		put_char(pInfo, DLE);
		put_char(pInfo, ETX);
		if (pInfo->flags & R3964_BCC) {
			put_char(pInfo, pInfo->bcc);
		}
		pInfo->state = R3964_WAIT_FOR_TX_ACK;
		mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
	}
	flush(pInfo);
}
コード例 #10
0
ファイル: n_r3964.c プロジェクト: ManiacTwister/linux-hnd
static void receive_char(struct r3964_info *pInfo, const unsigned char c)
{
	switch (pInfo->state) {
	case R3964_TX_REQUEST:
		if (c == DLE) {
			TRACE_PS("TX_REQUEST - got DLE");

			pInfo->state = R3964_TRANSMITTING;
			pInfo->tx_position = 0;

			transmit_block(pInfo);
		} else if (c == STX) {
			if (pInfo->nRetry == 0) {
				TRACE_PE("TX_REQUEST - init conflict");
				if (pInfo->priority == R3964_SLAVE) {
					goto start_receiving;
				}
			} else {
				TRACE_PE("TX_REQUEST - secondary init "
					"conflict!? Switching to SLAVE mode "
					"for next rx.");
				goto start_receiving;
			}
		} else {
			TRACE_PE("TX_REQUEST - char != DLE: %x", c);
			retry_transmit(pInfo);
		}
		break;
	case R3964_TRANSMITTING:
		if (c == NAK) {
			TRACE_PE("TRANSMITTING - got NAK");
			retry_transmit(pInfo);
		} else {
			TRACE_PE("TRANSMITTING - got invalid char");

			pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
		}
		break;
	case R3964_WAIT_FOR_TX_ACK:
		if (c == DLE) {
			TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
			remove_from_tx_queue(pInfo, R3964_OK);

			pInfo->state = R3964_IDLE;
			trigger_transmit(pInfo);
		} else {
			retry_transmit(pInfo);
		}
		break;
	case R3964_WAIT_FOR_RX_REPEAT:
		/* FALLTROUGH */
	case R3964_IDLE:
		if (c == STX) {
			/* Prevent rx_queue from overflow: */
			if (pInfo->blocks_in_rx_queue >=
			    R3964_MAX_BLOCKS_IN_RX_QUEUE) {
				TRACE_PE("IDLE - got STX but no space in "
						"rx_queue!");
				pInfo->state = R3964_WAIT_FOR_RX_BUF;
				mod_timer(&pInfo->tmr,
					  jiffies + R3964_TO_NO_BUF);
				break;
			}
start_receiving:
			/* Ok, start receiving: */
			TRACE_PS("IDLE - got STX");
			pInfo->rx_position = 0;
			pInfo->last_rx = 0;
			pInfo->flags &= ~R3964_ERROR;
			pInfo->state = R3964_RECEIVING;
			mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
			pInfo->nRetry = 0;
			put_char(pInfo, DLE);
			flush(pInfo);
			pInfo->bcc = 0;
		}
		break;
	case R3964_RECEIVING:
		if (pInfo->rx_position < RX_BUF_SIZE) {
			pInfo->bcc ^= c;

			if (c == DLE) {
				if (pInfo->last_rx == DLE) {
					pInfo->last_rx = 0;
					goto char_to_buf;
				}
				pInfo->last_rx = DLE;
				break;
			} else if ((c == ETX) && (pInfo->last_rx == DLE)) {
				if (pInfo->flags & R3964_BCC) {
					pInfo->state = R3964_WAIT_FOR_BCC;
					mod_timer(&pInfo->tmr,
						  jiffies + R3964_TO_ZVZ);
				} else {
					on_receive_block(pInfo);
				}
			} else {
				pInfo->last_rx = c;
char_to_buf:
				pInfo->rx_buf[pInfo->rx_position++] = c;
				mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
			}
		}
		/* else: overflow-msg? BUF_SIZE>MTU; should not happen? */
		break;
	case R3964_WAIT_FOR_BCC:
		pInfo->last_rx = c;
		on_receive_block(pInfo);
		break;
	}
}
コード例 #11
0
ファイル: n_r3964.c プロジェクト: ManiacTwister/linux-hnd
static void on_receive_block(struct r3964_info *pInfo)
{
	unsigned int length;
	struct r3964_client_info *pClient;
	struct r3964_block_header *pBlock;

	length = pInfo->rx_position;

	/* compare byte checksum characters: */
	if (pInfo->flags & R3964_BCC) {
		if (pInfo->bcc != pInfo->last_rx) {
			TRACE_PE("checksum error - got %x but expected %x",
				 pInfo->last_rx, pInfo->bcc);
			pInfo->flags |= R3964_CHECKSUM;
		}
	}

	/* check for errors (parity, overrun,...): */
	if (pInfo->flags & R3964_ERROR) {
		TRACE_PE("on_receive_block - transmission failed error %x",
			 pInfo->flags & R3964_ERROR);

		put_char(pInfo, NAK);
		flush(pInfo);
		if (pInfo->nRetry < R3964_MAX_RETRIES) {
			pInfo->state = R3964_WAIT_FOR_RX_REPEAT;
			pInfo->nRetry++;
			mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
		} else {
			TRACE_PE("on_receive_block - failed after max retries");
			pInfo->state = R3964_IDLE;
		}
		return;
	}

	/* received block; submit DLE: */
	put_char(pInfo, DLE);
	flush(pInfo);
	del_timer_sync(&pInfo->tmr);
	TRACE_PS(" rx success: got %d chars", length);

	/* prepare struct r3964_block_header: */
	pBlock = kmalloc(length + sizeof(struct r3964_block_header),
			GFP_KERNEL);
	TRACE_M("on_receive_block - kmalloc %p", pBlock);

	if (pBlock == NULL)
		return;

	pBlock->length = length;
	pBlock->data = ((unsigned char *)pBlock) +
			sizeof(struct r3964_block_header);
	pBlock->locks = 0;
	pBlock->next = NULL;
	pBlock->owner = NULL;

	memcpy(pBlock->data, pInfo->rx_buf, length);

	/* queue block into rx_queue: */
	add_rx_queue(pInfo, pBlock);

	/* notify attached client processes: */
	for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) {
		if (pClient->sig_flags & R3964_SIG_DATA) {
			add_msg(pClient, R3964_MSG_DATA, length, R3964_OK,
				pBlock);
		}
	}
	wake_up_interruptible(&pInfo->read_wait);

	pInfo->state = R3964_IDLE;

	trigger_transmit(pInfo);
}