// Write register to w9966 interface-chip // Expects a claimed pdev // 1 on success, else 0 static int w9966_wreg(struct w9966_dev* cam, int reg, int data) { // ECP, write, regtransfer, REG, REG, REG, REG, REG const u8 addr = 0xc0 | (reg & 0x1f); const u8 val = data; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0 || parport_write(cam->pport, &addr, 1) != 1 || parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0 || parport_write(cam->pport, &val, 1) != 1) return 0; return 1; }
/* Write register to W9966 interface-chip Expects a claimed pdev -1 on error */ static int w9966_write_reg(struct w9966 *cam, int reg, int data) { /* ECP, write, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0xc0 | (reg & 0x1f); const unsigned char val = data; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) return -1; if (parport_write(cam->pport, &addr, 1) != 1) return -1; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0) return -1; if (parport_write(cam->pport, &val, 1) != 1) return -1; return 0; }
/* Capture data */ static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct w9966 *cam = video_drvdata(file); unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */ unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; unsigned char *tbuf; /* Why would anyone want more than this?? */ if (count > cam->width * cam->height * 2) return -EINVAL; mutex_lock(&cam->lock); w9966_pdev_claim(cam); w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */ w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */ w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */ /* write special capture-addr and negotiate into data transfer */ if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) || (parport_write(cam->pport, &addr, 1) != 1) || (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) { w9966_pdev_release(cam); mutex_unlock(&cam->lock); return -EFAULT; } tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL); if (tbuf == NULL) { count = -ENOMEM; goto out; } while (dleft > 0) { unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; if (parport_read(cam->pport, tbuf, tsize) < tsize) { count = -EFAULT; goto out; } if (copy_to_user(dest, tbuf, tsize) != 0) { count = -EFAULT; goto out; } dest += tsize; dleft -= tsize; } w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */ out: kfree(tbuf); w9966_pdev_release(cam); mutex_unlock(&cam->lock); return count; }
// Read register from w9966 interface-chip // Expects a claimed pdev // -1 on error, else register data (byte) static int w9966_rreg(struct w9966_dev* cam, int reg) { // ECP, read, regtransfer, REG, REG, REG, REG, REG const u8 addr = 0x80 | (reg & 0x1f); u8 val; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0 || parport_write(cam->pport, &addr, 1) != 1 || parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0 || parport_read(cam->pport, &val, 1) != 1) return -1; return val; }
// Capture data static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) { struct w9966_dev *cam = (struct w9966_dev *)vdev->priv; unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 unsigned char* dest = (unsigned char*)buf; unsigned long dleft = count; // Why would anyone want more than this?? if (count > cam->width * cam->height * 2) return -EINVAL; w9966_pdev_claim(cam); w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer w9966_wReg(cam, 0x00, 0x00); // Return to normal operation w9966_wReg(cam, 0x01, 0x98); // Enable capture // write special capture-addr and negotiate into data transfer if ( (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )|| (parport_write(cam->pport, &addr, 1) != 1 )|| (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0 ) ) { w9966_pdev_release(cam); return -EFAULT; } while(dleft > 0) { unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; if (parport_read(cam->pport, cam->buffer, tsize) < tsize) { w9966_pdev_release(cam); return -EFAULT; } if (copy_to_user(dest, cam->buffer, tsize) != 0) { w9966_pdev_release(cam); return -EFAULT; } dest += tsize; dleft -= tsize; } w9966_wReg(cam, 0x01, 0x18); // Disable capture w9966_pdev_release(cam); return count; }
/* Read register from W9966 interface-chip Expects a claimed pdev -1 on error, else register data (byte) */ static int w9966_read_reg(struct w9966 *cam, int reg) { /* ECP, read, regtransfer, REG, REG, REG, REG, REG */ const unsigned char addr = 0x80 | (reg & 0x1f); unsigned char val; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0) return -1; if (parport_write(cam->pport, &addr, 1) != 1) return -1; if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0) return -1; if (parport_read(cam->pport, &val, 1) != 1) return -1; return val; }
// Capture data // expects a claimed parport and allocated read buffer static long w9966_v4l_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) { struct w9966_dev *cam = (struct w9966_dev *)vdev->priv; const u8 addr = 0xa0; // ECP, read, CCD-transfer, 00000 u8* dest = (u8*)buf; unsigned long dleft = count; // Why would anyone want more than this?? if (count > cam->width * cam->height * 2) count = cam->width * cam->height * 2; w9966_wreg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer w9966_wreg(cam, 0x00, 0x00); // Return to normal operation w9966_wreg(cam, 0x01, cam->cmask | 0x80); // Enable capture // write special capture-addr and negotiate into data transfer if (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 || parport_write(cam->pport, &addr, 1) != 1 || parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0) { DPRINTF("Unable to write capture-addr.\n"); return -EFAULT; } while(dleft > 0) { const size_t tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; if (parport_read(cam->pport, cam->buffer, tsize) < tsize) return -EFAULT; if (copy_to_user(dest, cam->buffer, tsize) != 0) return -EFAULT; dest += tsize; dleft -= tsize; } w9966_wreg(cam, 0x01, cam->cmask); // Disable capture return count; }
static int parport_init(void) { struct cable *cur_cable; cur_cable = cables; if(ser_open()) { printf("ser_open failed\n"); } parport_cable = "jtagproxy"; while (cur_cable->name) { if (strcmp(cur_cable->name, parport_cable) == 0) { cable = cur_cable; break; } cur_cable++; } if (!cable) { LOG_ERROR("No matching cable found for %s", parport_cable); return ERROR_JTAG_INIT_FAILED; } dataport_value = cable->PORT_INIT; parport_reset(0, 0); parport_write(0, 0, 0); parport_led(1); bitbang_interface = &parport_bitbang; return ERROR_OK; }
static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct w9966_dev *cam = vdev->priv; switch(cmd) { case VIDIOCGCAP: { static struct video_capability vcap = { .name = W9966_DRIVERNAME, .type = VID_TYPE_CAPTURE | VID_TYPE_SCALES, .channels = 1, .maxwidth = W9966_WND_MAX_W, .maxheight = W9966_WND_MAX_H, .minwidth = 2, .minheight = 1, }; struct video_capability *cap = arg; *cap = vcap; return 0; } case VIDIOCGCHAN: { struct video_channel *vch = arg; if(vch->channel != 0) // We only support one channel (#0) return -EINVAL; memset(vch,0,sizeof(*vch)); strcpy(vch->name, "CCD-input"); vch->type = VIDEO_TYPE_CAMERA; return 0; } case VIDIOCSCHAN: { struct video_channel *vch = arg; if(vch->channel != 0) return -EINVAL; return 0; } case VIDIOCGTUNER: { struct video_tuner *vtune = arg; if(vtune->tuner != 0) return -EINVAL; strcpy(vtune->name, "no tuner"); vtune->rangelow = 0; vtune->rangehigh = 0; vtune->flags = VIDEO_TUNER_NORM; vtune->mode = VIDEO_MODE_AUTO; vtune->signal = 0xffff; return 0; } case VIDIOCSTUNER: { struct video_tuner *vtune = arg; if (vtune->tuner != 0) return -EINVAL; if (vtune->mode != VIDEO_MODE_AUTO) return -EINVAL; return 0; } case VIDIOCGPICT: { struct video_picture vpic = { cam->brightness << 8, // brightness (cam->hue + 128) << 8, // hue cam->color << 9, // color cam->contrast << 9, // contrast 0x8000, // whiteness 16, VIDEO_PALETTE_YUV422// bpp, palette format }; struct video_picture *pic = arg; *pic = vpic; return 0; } case VIDIOCSPICT: { struct video_picture *vpic = arg; if (vpic->depth != 16 || (vpic->palette != VIDEO_PALETTE_YUV422 && vpic->palette != VIDEO_PALETTE_YUYV)) return -EINVAL; cam->brightness = vpic->brightness >> 8; cam->hue = (vpic->hue >> 8) - 128; cam->color = vpic->colour >> 9; cam->contrast = vpic->contrast >> 9; w9966_pdev_claim(cam); if ( w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 || w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 || w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 || w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1 ) { w9966_pdev_release(cam); return -EIO; } w9966_pdev_release(cam); return 0; } case VIDIOCSWIN: { int ret; struct video_window *vwin = arg; if (vwin->flags != 0) return -EINVAL; if (vwin->clipcount != 0) return -EINVAL; if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W) return -EINVAL; if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H) return -EINVAL; // Update camera regs w9966_pdev_claim(cam); ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height); w9966_pdev_release(cam); if (ret != 0) { DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n"); return -EIO; } return 0; } case VIDIOCGWIN: { struct video_window *vwin = arg; memset(vwin, 0, sizeof(*vwin)); vwin->width = cam->width; vwin->height = cam->height; return 0; } // Unimplemented case VIDIOCCAPTURE: case VIDIOCGFBUF: case VIDIOCSFBUF: case VIDIOCKEY: case VIDIOCGFREQ: case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; default: return -ENOIOCTLCMD; } return 0; } static int w9966_v4l_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return video_usercopy(inode, file, cmd, arg, w9966_v4l_do_ioctl); } // Capture data static ssize_t w9966_v4l_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct video_device *vdev = video_devdata(file); struct w9966_dev *cam = vdev->priv; unsigned char addr = 0xa0; // ECP, read, CCD-transfer, 00000 unsigned char __user *dest = (unsigned char __user *)buf; unsigned long dleft = count; unsigned char *tbuf; // Why would anyone want more than this?? if (count > cam->width * cam->height * 2) return -EINVAL; w9966_pdev_claim(cam); w9966_wReg(cam, 0x00, 0x02); // Reset ECP-FIFO buffer w9966_wReg(cam, 0x00, 0x00); // Return to normal operation w9966_wReg(cam, 0x01, 0x98); // Enable capture // write special capture-addr and negotiate into data transfer if ( (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0 )|| (parport_write(cam->pport, &addr, 1) != 1 )|| (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0 ) ) { w9966_pdev_release(cam); return -EFAULT; } tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL); if (tbuf == NULL) { count = -ENOMEM; goto out; } while(dleft > 0) { unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft; if (parport_read(cam->pport, tbuf, tsize) < tsize) { count = -EFAULT; goto out; } if (copy_to_user(dest, tbuf, tsize) != 0) { count = -EFAULT; goto out; } dest += tsize; dleft -= tsize; } w9966_wReg(cam, 0x01, 0x18); // Disable capture out: kfree(tbuf); w9966_pdev_release(cam); return count; } // Called once for every parport on init static void w9966_attach(struct parport *port) { int i; for (i = 0; i < W9966_MAXCAMS; i++) { if (w9966_cams[i].dev_state != 0) // Cam is already assigned continue; if ( strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0 ) { if (w9966_init(&w9966_cams[i], port) != 0) w9966_term(&w9966_cams[i]); break; // return } } }
static ssize_t pp_write (struct file * file, const char __user * buf, size_t count, loff_t * ppos) { unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_written = 0; ssize_t wrote; int mode; struct parport *pport; if (!(pp->flags & PP_CLAIMED)) { /* Don't have the port claimed */ pr_debug(CHRDEV "%x: claim the port first\n", minor); return -EINVAL; } kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); if (!kbuffer) { return -ENOMEM; } pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); parport_set_timeout (pp->pdev, (file->f_flags & O_NONBLOCK) ? PARPORT_INACTIVITY_O_NONBLOCK : pp->default_inactivity); while (bytes_written < count) { ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); if (copy_from_user (kbuffer, buf + bytes_written, n)) { bytes_written = -EFAULT; break; } if ((pp->flags & PP_FASTWRITE) && (mode == IEEE1284_MODE_EPP)) { /* do a fast EPP write */ if (pport->ieee1284.mode & IEEE1284_ADDR) { wrote = pport->ops->epp_write_addr (pport, kbuffer, n, PARPORT_EPP_FAST); } else { wrote = pport->ops->epp_write_data (pport, kbuffer, n, PARPORT_EPP_FAST); } } else { wrote = parport_write (pp->pdev->port, kbuffer, n); } if (wrote <= 0) { if (!bytes_written) { bytes_written = wrote; } break; } bytes_written += wrote; if (file->f_flags & O_NONBLOCK) { if (!bytes_written) bytes_written = -EAGAIN; break; } if (signal_pending (current)) { if (!bytes_written) { bytes_written = -EINTR; } break; } cond_resched(); } parport_set_timeout (pp->pdev, pp->default_inactivity); kfree (kbuffer); pp_enable_irq (pp); return bytes_written; }
static int parport_init(void) { const struct cable *cur_cable; #if PARPORT_USE_PPDEV == 1 char buffer[256]; #endif cur_cable = cables; if (parport_cable == NULL) { parport_cable = strdup("wiggler"); LOG_WARNING("No parport cable specified, using default 'wiggler'"); } while (cur_cable->name) { if (strcmp(cur_cable->name, parport_cable) == 0) { cable = cur_cable; break; } cur_cable++; } if (!cable) { LOG_ERROR("No matching cable found for %s", parport_cable); return ERROR_JTAG_INIT_FAILED; } dataport_value = cable->PORT_INIT; #if PARPORT_USE_PPDEV == 1 if (device_handle > 0) { LOG_ERROR("device is already opened"); return ERROR_JTAG_INIT_FAILED; } #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) LOG_DEBUG("opening /dev/ppi%d...", parport_port); snprintf(buffer, 256, "/dev/ppi%d", parport_port); device_handle = open(buffer, O_WRONLY); #else /* not __FreeBSD__, __FreeBSD_kernel__ */ LOG_DEBUG("opening /dev/parport%d...", parport_port); snprintf(buffer, 256, "/dev/parport%d", parport_port); device_handle = open(buffer, O_WRONLY); #endif /* __FreeBSD__, __FreeBSD_kernel__ */ if (device_handle < 0) { int err = errno; LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...open"); #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) int i = ioctl(device_handle, PPCLAIM); if (i < 0) { LOG_ERROR("cannot claim device"); return ERROR_JTAG_INIT_FAILED; } i = PARPORT_MODE_COMPAT; i = ioctl(device_handle, PPSETMODE, &i); if (i < 0) { LOG_ERROR(" cannot set compatible mode to device"); return ERROR_JTAG_INIT_FAILED; } i = IEEE1284_MODE_COMPAT; i = ioctl(device_handle, PPNEGOT, &i); if (i < 0) { LOG_ERROR("cannot set compatible 1284 mode to device"); return ERROR_JTAG_INIT_FAILED; } #endif /* not __FreeBSD__, __FreeBSD_kernel__ */ #else /* not PARPORT_USE_PPDEV */ if (parport_port == 0) { parport_port = 0x378; LOG_WARNING("No parport port specified, using default '0x378' (LPT1)"); } dataport = parport_port; statusport = parport_port + 1; LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport); #if PARPORT_USE_GIVEIO == 1 if (parport_get_giveio_access() != 0) { #else /* PARPORT_USE_GIVEIO */ if (ioperm(dataport, 3, 1) != 0) { #endif /* PARPORT_USE_GIVEIO */ LOG_ERROR("missing privileges for direct i/o"); return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("...privileges granted"); /* make sure parallel port is in right mode (clear tristate and interrupt */ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) outb(parport_port + 2, 0x0); #else outb(0x0, parport_port + 2); #endif #endif /* PARPORT_USE_PPDEV */ parport_reset(0, 0); parport_write(0, 0, 0); parport_led(1); bitbang_interface = &parport_bitbang; return ERROR_OK; } static int parport_quit(void) { parport_led(0); if (parport_exit) { dataport_value = cable->PORT_EXIT; parport_write_data(); } if (parport_cable) { free(parport_cable); parport_cable = NULL; } return ERROR_OK; }