Status SynchronousBuffer::MemoryCopy(void* src, size_t length)
{
	//TODO copy something to the memory;
	int rtn;
	if((rtn = pthread_mutex_lock(&bufferLock)) != 0)
		fprintf(stderr, "pthread_mutex_lock %d", rtn), exit(1);

	while(IsBufferFull(length)){
		if ((rtn = pthread_cond_wait(&bufferNotFull,&bufferLock)) != 0)
			fprintf(stderr, "pthread_cond_wait %d", rtn), exit(1);
	}

	memcpy(base+writePos,src,length);
	writePos = (writePos + length) % pageSize;

	if ((rtn = pthread_cond_broadcast(&bufferNotEmpty)) != 0)
		fprintf(stderr, "pthread_cond_signal %d", rtn), exit(1);

	pthread_mutex_unlock(&bufferLock);

	return OK;
}
Example #2
0
/*
 * callback for bulk IN urb
 */
static void cpcusb_read_bulk_callback(struct urb *urb)
{
	CPC_USB_T *card = (CPC_USB_T *) urb->context;
	CPC_CHAN_T *chan;
	unsigned char *ibuf = urb->transfer_buffer;
	int retval, msgCnt, start, again = 0;
	unsigned long flags;

	if (!card) {
		err("%s - device object lost", __func__);
		return;
	}

	spin_lock_irqsave(&card->slock, flags);

	if (!card->present) {
		spin_unlock_irqrestore(&card->slock, flags);
		info("%s - no such device", __func__);
		return;
	}

	switch (urb->status) {
	case 0:		/* success */
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		/* urb was killed */
		spin_unlock_irqrestore(&card->slock, flags);
		dbg("%s - read urb killed", __func__);
		return;
	default:
		info("%s - nonzero urb status %d", __func__, urb->status);
		break;
	}

	if (urb->actual_length) {
		msgCnt = ibuf[0] & ~0x80;
		again = ibuf[0] & 0x80;

		/* we have a 4 byte header */
		start = 4;
		chan = card->chan;
		while (msgCnt) {
			if (!(IsBufferFull(card->chan))) {
				start +=
				    cpcusb_unalign_and_copy_buffy((unsigned char *)
							  &chan->buf[chan->iidx], &ibuf[start]);

				if (start > urb->transfer_buffer_length) {
					err("%d > %d", start, urb->transfer_buffer_length);
					break;
				}

				chan->WnR = 0;
				chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT;
				msgCnt--;
			} else {
				break;
			}
		}
	}

	usb_fill_bulk_urb(urb, card->udev,
			  usb_rcvbulkpipe(card->udev, card->num_bulk_in),
			  urb->transfer_buffer,
			  urb->transfer_buffer_length,
			  cpcusb_read_bulk_callback, card);

	retval = usb_submit_urb(urb, GFP_ATOMIC);

	if (retval) {
		err("%s - failed resubmitting read urb, error %d", __func__, retval);
	}

	spin_unlock_irqrestore(&card->slock, flags);

	wake_up_interruptible(card->chan->CPCWait_q);
}
Example #3
0
static ssize_t cpcusb_write(struct file *file, const char *buffer,
			    size_t count, loff_t *ppos)
{
	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
	CPC_USB_WRITE_URB_T *wrUrb = NULL;

	ssize_t bytes_written = 0;
	int retval = 0;
	int j;

	unsigned char *obuf = NULL;
	unsigned char type = 0;
	CPC_MSG_T *info = NULL;

	dbg("%s - entered minor %d, count = %zu, present = %d",
	    __func__, card->minor, count, card->present);

	if (count > sizeof(CPC_MSG_T))
		return CPC_ERR_UNKNOWN;

	/* check if can read from the given address */
	if (!access_ok(VERIFY_READ, buffer, count))
		return CPC_ERR_UNKNOWN;

	/* lock this object */
	down(&card->sem);

	/* verify that the device wasn't unplugged */
	if (!card->present) {
		retval = CPC_ERR_NO_INTERFACE_PRESENT;
		goto exit;
	}

	/* verify that we actually have some data to write */
	if (count == 0) {
		dbg("%s - write request of 0 bytes", __func__);
		goto exit;
	}

	if (card->free_slots <= 5) {
		info = (CPC_MSG_T *) buffer;

		if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE
		    || card->free_slots <= 0) {
			dbg("%s - send buffer full please try again %d",
			    __func__, card->free_slots);
			retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
			goto exit;
		}
	}

	/* Find a free write urb */
	for (j = 0; j < CPC_USB_URB_CNT; j++) {
		if (!atomic_read(&card->wrUrbs[j].busy)) {
			wrUrb = &card->wrUrbs[j];	/* remember found URB */
			atomic_set(&wrUrb->busy, 1);	/* lock this URB      */
			init_completion(&wrUrb->finished);	/* init completion    */
			dbg("WR URB no. %d started", j);
			break;
		}
	}

	/* don't found write urb say error */
	if (!wrUrb) {
		dbg("%s - no free send urb available", __func__);
		retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
		goto exit;
	}
	dbg("URB write req");

	obuf = (unsigned char *) wrUrb->urb->transfer_buffer;

	/* copy the data from userspace into our transfer buffer;
	 * this is the only copy required.
	 */
	if (copy_from_user(&obuf[4], buffer, count) != 0) {
		atomic_set(&wrUrb->busy, 0);	/* release urb */
		retval = CPC_ERR_IO_TRANSFER;
		goto exit;
	}

	/* check if it is a DRIVER information message, so we can
	 * response to that message and not the USB
	 */
	info = (CPC_MSG_T *) &obuf[4];

	bytes_written = 11 + info->length;
	if (bytes_written >= wrUrb->size) {
		retval = CPC_ERR_IO_TRANSFER;
		goto exit;
	}

	switch (info->type) {
	case CPC_CMD_T_CLEAR_MSG_QUEUE:
		ResetBuffer(card->chan);
		break;

	case CPC_CMD_T_INQ_MSG_QUEUE_CNT:
		retval = cpc_get_buffer_count(card->chan);
		atomic_set(&wrUrb->busy, 0);

		goto exit;

	case CPC_CMD_T_INQ_INFO:
		if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) {
			/* release urb cause we'll use it for driver
			 * information
			 */
			atomic_set(&wrUrb->busy, 0);
			if (IsBufferFull(card->chan)) {
				retval = CPC_ERR_IO_TRANSFER;
				goto exit;
			}

			/* it is a driver information request message and we have
			 * free rx slots to store the response
			 */
			type = info->msg.info.type;
			info = &card->chan->buf[card->chan->iidx];

			info->type = CPC_MSG_T_INFO;
			info->msg.info.source = CPC_INFOMSG_T_DRIVER;
			info->msg.info.type = type;

			switch (type) {
			case CPC_INFOMSG_T_VERSION:
				info->length = strlen(CPC_DRIVER_VERSION) + 2;
				sprintf(info->msg.info.msg, "%s\n",
					CPC_DRIVER_VERSION);
				break;

			case CPC_INFOMSG_T_SERIAL:
				info->length = strlen(CPC_DRIVER_SERIAL) + 2;
				sprintf(info->msg.info.msg, "%s\n",
					CPC_DRIVER_SERIAL);
				break;

			default:
				info->length = 2;
				info->msg.info.type =
				    CPC_INFOMSG_T_UNKNOWN_TYPE;
			}

			card->chan->WnR = 0;
			card->chan->iidx =
			    (card->chan->iidx + 1) % CPC_MSG_BUF_CNT;

			retval = info->length;
			goto exit;
		}
		break;
	case CPC_CMD_T_CAN_PRMS:
		/* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */
		if (info->msg.canparams.cc_type != SJA1000
		    && info->msg.canparams.cc_type != M16C_BASIC
		    && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID
			&& info->msg.canparams.cc_type != SJA1000)) {
			/* don't forget to release the urb */
			atomic_set(&wrUrb->busy, 0);
			retval = CPC_ERR_WRONG_CONTROLLER_TYPE;
			goto exit;
		}
		break;
	}

	/* just convert the params if it is an old CPC-USB with M16C controller */
	if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) {
		/* if it is a parameter message convert it from SJA1000 controller
		 * settings to M16C Basic controller settings
		 */
		SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]);
	}

	/* don't forget the byte alignment */
	cpcusb_align_buffer_alignment(&obuf[4]);

	/* setup a the 4 byte header */
	obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0;

	/* this urb was already set up, except for this write size */
	wrUrb->urb->transfer_buffer_length = bytes_written + 4;

	/* send the data out the bulk port */
	/* a character device write uses GFP_KERNEL,
	   unless a spinlock is held */
	retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL);
	if (retval) {
		atomic_set(&wrUrb->busy, 0);	/* release urb */
		err("%s - failed submitting write urb, error %d",
		    __func__, retval);
	} else {
		retval = bytes_written;
	}

exit:
	/* unlock the device */
	up(&card->sem);

	dbg("%s - leaved", __func__);

	return retval;
}