📄 ser_avrdoper.c
字号:
/* fprintf(stderr, "seen product ->%s<-\n", string); */ if(strcmp(string, productName) == 0) break; } } } usb_close(handle); handle = NULL; } } if(handle) break; } if(handle != NULL){ int rval, retries = 3; if(usb_set_configuration(handle, 1)){ fprintf(stderr, "Warning: could not set configuration: %s\n", 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){ fprintf(stderr, "Warning: could not detach kernel HID driver: %s\n", usb_strerror()); }#endif } if(rval != 0) fprintf(stderr, "Warning: could not claim interface\n");/* Continue anyway, even if we could not claim the interface. Control transfers * should still work. */ errorCode = 0; *device = handle; usesReportIDs = _usesReportIDs; } return errorCode;}/* ------------------------------------------------------------------------- */static void usbCloseDevice(usbDevice_t *device){ if(device != NULL) usb_close(device);}/* ------------------------------------------------------------------------- */static int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len){int bytesSent; if(!usesReportIDs){ buffer++; /* skip dummy report ID */ len--; } bytesSent = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, reportType << 8 | buffer[0], 0, buffer, len, 5000); if(bytesSent != len){ if(bytesSent < 0) fprintf(stderr, "Error sending message: %s\n", usb_strerror()); return USB_ERROR_IO; } return 0;}/* ------------------------------------------------------------------------- */static int usbGetReport(usbDevice_t *device, int reportType, int reportNumber, char *buffer, int *len){int bytesReceived, maxLen = *len; if(!usesReportIDs){ buffer++; /* make room for dummy report ID */ maxLen--; } bytesReceived = usb_control_msg(device, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, reportType << 8 | reportNumber, 0, buffer, maxLen, 5000); if(bytesReceived < 0){ fprintf(stderr, "Error sending message: %s\n", usb_strerror()); return USB_ERROR_IO; } *len = bytesReceived; if(!usesReportIDs){ buffer[-1] = reportNumber; /* add dummy report ID */ *len++; } return 0;}#endif /* WIN32NATIVE *//* ------------------------------------------------------------------------ *//* ------------------------------------------------------------------------ *//* ------------------------------------------------------------------------ */#include "ser_avrdoper.h"#include "serial.h"#define USB_VENDOR_ID 0x16c0#define USB_PRODUCT_ID 0x05dfextern char *progname;extern int verbose;static usbDevice_t *device = NULL;/* ------------------------------------------------------------------------- */static void dumpBlock(char *prefix, unsigned char *buf, int len){int i; if(len <= 8){ /* more compact format for short blocks */ fprintf(stderr, "%s: %d bytes: ", prefix, len); for(i = 0; i < len; i++){ fprintf(stderr, "%02x ", buf[i]); } fprintf(stderr, " \""); for(i = 0; i < len; i++){ if(buf[i] >= 0x20 && buf[i] < 0x7f){ fputc(buf[i], stderr); }else{ fputc('.', stderr); } } fprintf(stderr, "\"\n"); }else{ fprintf(stderr, "%s: %d bytes:\n", prefix, len); while(len > 0){ for(i = 0; i < 16; i++){ if(i < len){ fprintf(stderr, "%02x ", buf[i]); }else{ fprintf(stderr, " "); } if(i == 7) fputc(' ', stderr); } fprintf(stderr, " \""); for(i = 0; i < 16; i++){ if(i < len){ if(buf[i] >= 0x20 && buf[i] < 0x7f){ fputc(buf[i], stderr); }else{ fputc('.', stderr); } } } fprintf(stderr, "\"\n"); buf += 16; len -= 16; } }}static char *usbErrorText(int usbErrno){static char buffer[32]; switch(usbErrno){ case USB_ERROR_NONE: return "Success."; case USB_ERROR_ACCESS: return "Access denied.\nIf running on Linux, check /proc/bus/usb permissions."; case USB_ERROR_NOTFOUND:return "Device not found."; case USB_ERROR_BUSY: return "Device is busy."; case USB_ERROR_IO: return "I/O Error."; default: sprintf(buffer, "Unknown error %d.", usbErrno); return buffer; }}/* ------------------------------------------------------------------------- */static int avrdoper_open(char *port, long baud){int rval;char *vname = "obdev.at";char *devname = "AVR-Doper"; if(device != NULL){ /* we support only one open device */ fprintf(stderr, "%s: avrdoper_open(): already open, only one open device supported!\n", progname); exit(1); } rval = usbOpenDevice(&device, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1); if(rval != 0){ fprintf(stderr, "%s: avrdoper_open(): %s\n", progname, usbErrorText(rval)); exit(1); } return 0;}/* ------------------------------------------------------------------------- */static int avrdoper_setspeed(int fd, long baud){ /* dummy */ return 0;}/* ------------------------------------------------------------------------- */static void avrdoper_close(int fd){ if(device == NULL){ fprintf(stderr, "%s: avrdoper_close(): Device never opened (fd=%d)\n", progname, fd); exit(1); } usbCloseDevice(device); device = NULL;}/* ------------------------------------------------------------------------- */static int reportDataSizes[4] = {13, 29, 61, 125};static int chooseDataSize(int len){int i; for(i = 0; i < sizeof(reportDataSizes)/sizeof(reportDataSizes[0]); i++){ if(reportDataSizes[i] >= len) return i; } return i - 1;}static int avrdoper_send(int fd, 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(device, 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;}/* ------------------------------------------------------------------------- */static unsigned char avrdoperRxBuffer[280]; /* buffer for receive data */static int avrdoperRxLength = 0; /* amount of valid bytes in rx buffer */static int avrdoperRxPosition = 0; /* amount of bytes already consumed in rx buffer */static void avrdoperFillBuffer(void){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(device, 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; }}static int avrdoper_recv(int fd, unsigned char *buf, size_t buflen){unsigned char *p = buf;int remaining = buflen; while(remaining > 0){ int len, available = avrdoperRxLength - avrdoperRxPosition; if(available <= 0){ /* buffer is empty */ avrdoperFillBuffer(); continue; } len = remaining < available ? remaining : available; memcpy(p, avrdoperRxBuffer + avrdoperRxPosition, len); p += len; remaining -= len; avrdoperRxPosition += len; } if(verbose > 3) dumpBlock("Receive", buf, buflen); return 0;}/* ------------------------------------------------------------------------- */static int avrdoper_drain(int fd, int display){ do{ avrdoperFillBuffer(); }while(avrdoperRxLength > 0); return 0;}/* ------------------------------------------------------------------------- */struct serial_device avrdoper_serdev ={ .open = avrdoper_open, .setspeed = avrdoper_setspeed, .close = avrdoper_close, .send = avrdoper_send, .recv = avrdoper_recv, .drain = avrdoper_drain,};#endif /* defined(HAVE_LIBUSB) || defined(WIN32NATIVE) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -