static void avrdoperFillBuffer(union filedescriptor *fdp) { int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */ avrdoperRxPosition = avrdoperRxLength = 0; while(bytesPending > 0){ int len, usbErr, lenIndex = chooseDataSize(bytesPending); unsigned char buffer[128]; len = sizeof(avrdoperRxBuffer) - avrdoperRxLength; /* bytes remaining */ if(reportDataSizes[lenIndex] + 2 > len) /* requested data would not fit into buffer */ break; len = reportDataSizes[lenIndex] + 2; usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1, (char *)buffer, &len); if(usbErr != 0){ fprintf(stderr, "%s: avrdoperFillBuffer(): %s\n", progname, usbErrorText(usbErr)); exit(1); } if(verbose > 3) fprintf(stderr, "Received %d bytes data chunk of total %d\n", len - 2, buffer[1]); len -= 2; /* compensate for report ID and length byte */ bytesPending = buffer[1] - len; /* amount still buffered */ if(len > buffer[1]) /* cut away padding */ len = buffer[1]; if(avrdoperRxLength + len > sizeof(avrdoperRxBuffer)){ fprintf(stderr, "%s: avrdoperFillBuffer(): internal error: buffer overflow\n", progname); exit(1); } memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len); avrdoperRxLength += len; } }
/** * API: Poll for any pressed keys. Converts the bitmap of keys pressed into a * scancode (1-4) for each pressed key. * \note Only single key presses are detected. */ unsigned char glcd2usb_poll_keys(PrivateData *p) { CT_glcd2usb_data *ctd = (CT_glcd2usb_data *) p->ct_data; unsigned char keycode = 0; int err = 0, len = 2; int i; if ((err = usbGetReport(ctd->device, USB_HID_REPORT_TYPE_FEATURE, GLCD2USB_RID_GET_BUTTONS, ctd->tx_buffer.bytes, &len)) != 0) { p->glcd_functions->drv_report(RPT_ERR, "glcd2usb_poll_keys: Error getting button state: %s", usbErrorMessage(err)); return 0; } for (i = 0; i < 4; i++) { if (ctd->tx_buffer.bytes[1] & (1 << i)) { keycode = i + 1; break; } } return keycode; }
/** * 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; }
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; }