/* libusb test: control TAKARA TOMY's Glitter panel (16x16 LED module) references: http://penguin.tantin.jp/hard/libusb%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.html http://www.nc.ie.u-ryukyu.ac.jp/studentlab/index.php?libusb http://d.hatena.ne.jp/tch/20091110 http://www.mail-archive.com/freebsd-users-jp@jp.freebsd.org/msg01708.html --- public domain, no warranty. */ #include #include #include #include #include #include // libusb extern uint16_t Doubler[]; extern uint8_t FontData[]; /* display one character */ static void display_character(struct usb_dev_handle *dev, unsigned char c, int msec) { #define EP_ADR_IN 0x81 #define EP_ADR_OUT 0x02 int i; char buf[6 + 32 + 8], *b; buf[0] = 0x80; buf[1] = 0x03; buf[2] = 0x5c; // bit[3:2] brightness (00:25% 01:50% 10:75% 11:100%) buf[3] = 0x08; buf[4] = 0x00; buf[5] = 0x00; b = &buf[6]; // start position of data for (i = 0; i < 8; i++) { *b++ = Doubler[FontData[c * 8 + i]] >> 8; // left 8px *b++ = Doubler[FontData[c * 8 + i]]; // right 8px *b++ = Doubler[FontData[c * 8 + i]] >> 8; // left 8px *b++ = Doubler[FontData[c * 8 + i]]; // right 8px } /* add 1 packet to synch toggle bit */ // total 6 packets to device (the extra is ignored) for (i = 0; i < 8; i++) { *b++ = 0x00; } /* send data */ if (usb_interrupt_write(dev, EP_ADR_OUT, buf, sizeof(buf), 0) < 0) { printf("usb_interrupt_write %s\n", usb_strerror()); } /* delay to next character */ usleep(msec * 1000); return; } /* action */ static void do_action(struct usb_device *dev, char *string, int msec) { int i; usb_dev_handle *dh; /* open device */ dh = usb_open(dev); if (dh == NULL) { printf("usb_open NULL\n"); goto fin0; } /* set configuration */ if (usb_set_configuration(dh, dev->config->bConfigurationValue) < 0) { printf("usb_set_configuration %s\n", usb_strerror()); goto fin1; } /* claim interface */ if (usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber) < 0) { printf("usb_claim_interface %s\n", usb_strerror()); goto fin1; } /* send data to USB */ for (i = 0; i < strlen(string); i++) { display_character(dh, string[i], msec); } /* clear display */ display_character(dh, ' ', msec); //fin2: usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber); fin1: usb_close(dh); fin0: return; } /* test main */ static void usb_test(char *string, int msec) { #define VENDOR_ID 0x0f30 #define PRODUCT_ID 0x0040 struct usb_bus *bus; struct usb_device *dev; int found, bnum, dnum; /* initialize libusb */ usb_init(); usb_find_busses(); usb_find_devices(); /* no device as default */ found = 0; /* find device */ for (bus = usb_get_busses(), bnum = 0; bus != NULL; bus = bus->next, bnum++) { for (dev = bus->devices, dnum = 0; dev != NULL; dev = dev->next, dnum++) { if (dev->descriptor.idVendor == VENDOR_ID && dev->descriptor.idProduct == PRODUCT_ID) { found = 1; goto found; } } } found: /* do action when device is found */ if (found) { printf("device at %03d:%03d\n", bnum, dnum); do_action(dev, string, msec); } else { printf("device not found\n"); } return; } int main(int argc, char *argv[]) { int msec; if (argc < 3) { printf("usage: %s [delay(msec)] [string]\n", argv[0]); return 0; } msec = atoi(argv[1]); usb_test(argv[2], msec); return 0; }