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; }
/* * 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); }
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; }