static int avrdoper_send(union filedescriptor *fdp, unsigned char *buf, size_t buflen)
{
    if(verbose > 3)
        dumpBlock("Send", buf, buflen);
    while(buflen > 0){
        unsigned char buffer[256];
        int rval, lenIndex = chooseDataSize(buflen);
        int thisLen = buflen > reportDataSizes[lenIndex] ?
	    reportDataSizes[lenIndex] : buflen;
        buffer[0] = lenIndex + 1;   /* report ID */
        buffer[1] = thisLen;
        memcpy(buffer + 2, buf, thisLen);
        if(verbose > 3)
            fprintf(stderr, "Sending %d bytes data chunk\n", thisLen);
        rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer,
			    reportDataSizes[lenIndex] + 2);
        if(rval != 0){
            fprintf(stderr, "%s: avrdoper_send(): %s\n", progname, usbErrorText(rval));
            exit(1);
        }
        buflen -= thisLen;
        buf += thisLen;
    }
    return 0;
}
Beispiel #2
0
/**
 * API: Set the backlight brightness
 */
void
glcd2usb_backlight(PrivateData *p, int state)
{
	int err = 0;
	CT_glcd2usb_data *ctd = (CT_glcd2usb_data *) p->ct_data;
	int promille = (state == BACKLIGHT_ON) ? p->brightness : p->offbrightness;

	ctd->tx_buffer.bytes[0] = GLCD2USB_RID_SET_BL;
	ctd->tx_buffer.bytes[1] = promille * 255 / 1000;

	p->glcd_functions->drv_debug(RPT_DEBUG, "glcd2usb_backlight: new value = %d",
		ctd->tx_buffer.bytes[1]);

	if ((err = usbSetReport(ctd->device, USB_HID_REPORT_TYPE_FEATURE, ctd->tx_buffer.bytes, 2)) != 0) {
		p->glcd_functions->drv_report(RPT_ERR, "Error freeing display: %s\n", usbErrorMessage(err));
	}
}
Beispiel #3
0
/**
 * API: Initialize glcd2usb connection type.
 */
int
glcd2usb_init(Driver *drvthis)
{
	PrivateData *p = (PrivateData *)drvthis->private_data;
	CT_glcd2usb_data *ctd;

	static int didUsbInit = 0;
	struct usb_bus *bus;
	struct usb_device *dev;
	usb_dev_handle *handle = NULL;
	int err = 0;
	int rval, retries = 3;
	int len;

	/* Set up connection type low-level functions */
	p->glcd_functions->blit = glcd2usb_blit;
	p->glcd_functions->close = glcd2usb_close;
	p->glcd_functions->set_backlight = glcd2usb_backlight;
	p->glcd_functions->poll_keys = glcd2usb_poll_keys;

	/* Allocate memory structures */
	ctd = (CT_glcd2usb_data *) calloc(1, sizeof(CT_glcd2usb_data));
	if (ctd == NULL) {
		report(RPT_ERR, "%s/glcd2usb: error allocating connection data", drvthis->name);
		return -1;
	}
	p->ct_data = ctd;

	/*
	 * Try to find and open a device. Only the first device found will be
	 * recognized.
	 */
	if (!didUsbInit) {
		usb_init();
		didUsbInit = 1;
	}

	usb_find_busses();
	usb_find_devices();

	for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
		for (dev = bus->devices; dev != NULL; dev = dev->next) {

			if (dev->descriptor.idVendor == GLCD2USB_VID
			    && dev->descriptor.idProduct == GLCD2USB_PID) {

				handle = usb_open(dev);
				if (!handle) {
					report(RPT_WARNING, "%s/glcd2usb: cannot open USB device: %s",
					       drvthis->name, usb_strerror());
					continue;
				}
				else {
					goto found_dev;
				}
			}
		}
	}

found_dev:
	if (handle) {
		debug(RPT_DEBUG, "%s/glcd2usb: opening device succeeded", drvthis->name);
	}
	else {
		report(RPT_ERR, "%s/glcd2usb: no GLCD2USB device found", drvthis->name);
		goto err_out;
	}

	if (usb_set_configuration(handle, 1))
		report(RPT_WARNING, "%s/glcd2usb: could not set configuration: %s",
		       drvthis->name, usb_strerror());

	/*
	 * now try to claim the interface and detach the kernel HID driver on
	 * Linux and other operating systems which support the call.
	 */
	while ((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0) {
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
		if (usb_detach_kernel_driver_np(handle, 0) < 0) {
			report(RPT_WARNING, "%s/glcd2usb: could not detach kernel HID driver: %s",
			       drvthis->name, usb_strerror());
		}
#endif
	}
	if (rval != 0)
		report(RPT_WARNING, "%s/glcd2usb: could not claim interface", drvthis->name);

	/*
	 * Continue anyway, even if we could not claim the interface. Control
	 * transfers should still work.
	 */
	ctd->device = handle;

	/* Query device */
	memset(&(ctd->tx_buffer), 0, sizeof(ctd->tx_buffer));
	len = sizeof(display_info_t);

	if ((err = usbGetReport(ctd->device, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_INFO, ctd->tx_buffer.bytes, &len)) != 0) {
		report(RPT_ERR, "%s/glcd2usb: query display parameters: %s",
		       drvthis->name, usbErrorMessage(err));
		goto err_out;
	}

	if (len < (int)sizeof(ctd->tx_buffer.display_info)) {
		report(RPT_ERR, "%s/glcd2usb: incomplete display info report (%d instead of %d)",
		       drvthis->name, len, (int)sizeof(ctd->tx_buffer.display_info));
		goto err_out;
	}

	if (!(ctd->tx_buffer.display_info.flags & FLAG_VERTICAL_UNITS)) {
		report(RPT_ERR, "%s/glcd2usb: unsupported display layout", drvthis->name);
		goto err_out;
	}

	if (ctd->tx_buffer.display_info.width > GLCD_MAX_WIDTH
	    || ctd->tx_buffer.display_info.width <= 0
	    || ctd->tx_buffer.display_info.height > GLCD_MAX_HEIGHT
	    || ctd->tx_buffer.display_info.height <= 0) {
		report(RPT_ERR, "%s/glcd2usb: display size out of range: %dx%d",
		       drvthis->name, ctd->tx_buffer.display_info.width,
		       ctd->tx_buffer.display_info.height);
		goto err_out;
	}
	p->framebuf.layout = FB_TYPE_VPAGED;
	p->framebuf.px_width = ctd->tx_buffer.display_info.width;
	p->framebuf.px_height = ctd->tx_buffer.display_info.height;
	p->framebuf.size = (p->framebuf.px_height + 7) / 8 * p->framebuf.px_width;
	report(RPT_INFO, "%s/glcd2usb: using display size %dx%d", drvthis->name,
	       ctd->tx_buffer.display_info.width, ctd->tx_buffer.display_info.height);

	ctd->paged_buffer = malloc(p->framebuf.size);
	if (ctd->paged_buffer == NULL) {
		report(RPT_ERR, "%s/glcd2usb: cannot allocate memory", drvthis->name);
		goto err_out;
	}
	memset(ctd->paged_buffer, 0x55, p->framebuf.size);

	ctd->dirty_buffer = malloc(p->framebuf.size);
	if (ctd->dirty_buffer == NULL) {
		report(RPT_ERR, "%s/glcd2usb: cannot allocate memory", drvthis->name);
		goto err_out;
	}

	/* Allocate the display (turn off the 'whirl') */
	ctd->tx_buffer.bytes[0] = GLCD2USB_RID_SET_ALLOC;
	ctd->tx_buffer.bytes[1] = 1;
	if ((err = usbSetReport(ctd->device, USB_HID_REPORT_TYPE_FEATURE, ctd->tx_buffer.bytes, 2)) != 0) {
		report(RPT_ERR, "%s/glcd2usb: Error allocating display: %s",
		       drvthis->name, usbErrorMessage(err));
		goto err_out;
	}

	return 0;

err_out:
	glcd2usb_close(p);
	return -1;
}
Beispiel #4
0
/**
 * API: Transfer an image to the glcd2usb device. This function and its update
 * algorithm are copied from the LCD4Linux driver as it does its job well.
 */
void
glcd2usb_blit(PrivateData *p)
{
	CT_glcd2usb_data *ctd = (CT_glcd2usb_data *) p->ct_data;
	int r;
	int i, j;
	int err;
	int pos;

	p->glcd_functions->drv_debug(RPT_DEBUG, "glcd2usb_blit: starting");

	/* Reset the dirty buffer */
	memset(ctd->dirty_buffer, 0x00, p->framebuf.size);

	/*
	 * Step 1: Compare the content of the secondary buffer with the frame
	 * buffer and copy the differences. For each different byte, set the
	 * flag in the dirty buffer.
	 */
	for (pos = 0; pos < p->framebuf.size; pos++) {
		if (ctd->paged_buffer[pos] != p->framebuf.data[pos]) {
			ctd->paged_buffer[pos] = p->framebuf.data[pos];
			ctd->dirty_buffer[pos] = 1;
		}
	}

	/*
	 * Step 2: Short gaps of unchanged bytes in fact increase the
	 * communication overhead. So we eliminate them here.
	 */
	for (j = -1, i = 0; i < p->framebuf.size; i++) {
		if (ctd->dirty_buffer[i] && j >= 0 && i - j <= 4) {
			/* found a clean gap <= 4 bytes: mark it dirty */
			for (r = j; r < i; r++)
				ctd->dirty_buffer[r] = 1;
		}

		/* if this is dirty, drop the saved position */
		if (ctd->dirty_buffer[i])
			j = -1;

		/* save position of this clean entry if no position saved yet */
		if (!ctd->dirty_buffer[i] && j < 0)
			j = i;
	}

	/* Step 3: Send the changes. */
	ctd->tx_buffer.bytes[0] = 0;
	for (i = 0; i < p->framebuf.size; i++) {
		if (ctd->dirty_buffer[i]) {
			/* Start a new packet */
			if (!ctd->tx_buffer.bytes[0]) {
				ctd->tx_buffer.bytes[0] = GLCD2USB_RID_WRITE;
				ctd->tx_buffer.bytes[1] = i % 256;
				ctd->tx_buffer.bytes[2] = i / 256;
				ctd->tx_buffer.bytes[3] = 0;	/* length */
			}
			/* Append the dirty byte and increase size */
			ctd->tx_buffer.bytes[4 + ctd->tx_buffer.bytes[3]++] = ctd->paged_buffer[i];
		}

		/*
		 * Send the data if we hit a clean byte, are at the end of
		 * the frame or reached the maximum payload for a write
		 * request.
		 */
		if (!ctd->dirty_buffer[i] || i == p->framebuf.size - 1 || ctd->tx_buffer.bytes[3] == 128) {
			/* Only write if there IS something to be written */
			if (ctd->tx_buffer.bytes[0] == GLCD2USB_RID_WRITE && ctd->tx_buffer.bytes[3] > 0) {
				err = usbSetReport(ctd->device, USB_HID_REPORT_TYPE_FEATURE,
						   ctd->tx_buffer.bytes, ctd->tx_buffer.bytes[3] + 4);
				if (err)
					p->glcd_functions->drv_report(RPT_ERR, "glcd2usb_blit: error in transfer");
				/* Start a new packet the next time */
				ctd->tx_buffer.bytes[0] = 0;
			}
		}
	}
}
Beispiel #5
0
static int uploadData(char *dataBuffer)
{
usbDevice_t *dev = NULL;
int         err = 0, len, mask, pageSize, deviceSize, i;
union{
    char            bytes[1];
    deviceInfo_t    info;
    deviceData_t    data;
}           buffer;

    if((err = usbOpenDevice(&dev, IDENT_VENDOR_NUM, IDENT_VENDOR_STRING, IDENT_PRODUCT_NUM, IDENT_PRODUCT_STRING, 1)) != 0){
        fprintf(stderr, "Error opening HIDBoot device: %s\n", usbErrorMessage(err));
        goto errorOccurred;
    }
    len = sizeof(buffer);
    if(endAddress[addressIndex] > startAddress[0]){    // we need to upload data
        if((err = usbGetReport(dev, USB_HID_REPORT_TYPE_FEATURE, 1, buffer.bytes, &len)) != 0){
            fprintf(stderr, "Error reading page size: %s\n", usbErrorMessage(err));
            goto errorOccurred;
        }
        if(len < sizeof(buffer.info)){
            fprintf(stderr, "Not enough bytes in device info report (%d instead of %d)\n", len, (int)sizeof(buffer.info));
            err = -1;
            goto errorOccurred;
        }
        pageSize = getUsbInt(buffer.info.pageSize, 2);
        deviceSize = getUsbInt(buffer.info.flashSize, 4);
        printf("Page size   = %d (0x%x)\n", pageSize, pageSize);
        printf("Device size = %d (0x%x); %d bytes remaining\n", deviceSize, deviceSize, deviceSize - 2048);
        if(endAddress[addressIndex] > deviceSize - 2048){
            fprintf(stderr, "Data (%d bytes) exceeds remaining flash size!\n", endAddress[addressIndex]);
            err = -1;
            goto errorOccurred;
        }
        if(pageSize < 128){
            mask = 127;
        }else{
            mask = pageSize - 1;
        }
        for (i = 0; i <= addressIndex; i++)
        {
           startAddress[i] &= ~mask;                  /* round down */
           endAddress[i] = (endAddress[i] + mask) & ~mask;  /* round up */
           printf("Uploading %d (0x%x) bytes starting at %d (0x%x)\n", endAddress[i] - startAddress[i], endAddress[i] - startAddress[i], startAddress[i], startAddress[i]);
           while(startAddress[i] < endAddress[i]){
               buffer.data.reportId = 2;
               memcpy(buffer.data.data, dataBuffer + startAddress[i], 128);
               setUsbInt(buffer.data.address, startAddress[i], 3);
               printf("\r0x%05x ... 0x%05x", startAddress[i], startAddress[i] + (int)sizeof(buffer.data.data));
               fflush(stdout);
               if((err = usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, sizeof(buffer.data))) != 0){
                   //fprintf(stderr, "Error uploading data block: %s\n", usbErrorMessage(err));
                   continue;
                   goto errorOccurred;
               }
               startAddress[i] += sizeof(buffer.data.data);
           }
           printf("\n");
        }
    }
    if(leaveBootLoader){
        /* and now leave boot loader: */
        buffer.info.reportId = 1;
        usbSetReport(dev, USB_HID_REPORT_TYPE_FEATURE, buffer.bytes, sizeof(buffer.info));
        /* Ignore errors here. If the device reboots before we poll the response,
         * this request fails.
         */
    }
errorOccurred:
    if(dev != NULL)
        usbCloseDevice(dev);
    return err;
}