// Note: I have 198 LEDs // 0 - 118 front // 119 - 197 back #include #include #include #include #include #define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */ #define USBDEV_SHARED_PRODUCT 0x05dc /* Obdev's free shared PID */ #define PRODUCT_NAME "LED-Strip" #define PRODUCT_MANFG "markus@notsyncing.net" #define BLOCKSIZE 200 #define BLOCKCOUNT 12 #define CMD_PING 0 #define CMD_SWVERSION 1 #define CMD_EEWRITE 2 #define CMD_EEREAD 3 #define CMD_EEOPEN 4 // Can be used if errors occour while writing to the device. #define CMD_RESET 5 // WDT RESET #define CMD_SETBLOCK 9 #define CMD_SETLED 10 #define BLOCK_META_RENDER 254 struct shell_state { int run; int current_block; }; struct command_list_struct { char *regex; char *help; int (*funcPtr)(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); }; int command_help(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int command_exit(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int command_block(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int command_set_led_single(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int command_set_led_multi(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int command_error(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info); int set_block(struct usb_dev_handle *dev, int block); int set_led(struct usb_dev_handle *dev, int block, int led, int r, int g, int b); int set_templed(struct usb_dev_handle *dev, int block, int led, int r, int g, int b); int cmd_set_led(struct usb_dev_handle *dev, int block, int led, int lede, int r, int g, int b); struct command_list_struct command_list[] = { { .help = "block \tSelect the current block.", .regex = "block (\\d*)", .funcPtr = command_block }, { .help = "exit\tTerminate the program.", .regex = "exit", .funcPtr = command_exit }, { .help = "help\t Show this text.", .regex = "help", .funcPtr = command_help }, { .help = "tled \t Set the LED's RGB color temporarily.", .regex = "(tled) (\\d*) (\\d*) (\\d*) (\\d*)", .funcPtr = command_set_led_single }, { .help = "tled \t Set the color of multiple LEDs temporarily.", .regex = "(tled) (\\d*)-(\\d*) (\\d*) (\\d*) (\\d*)", .funcPtr = command_set_led_multi }, { .help = "led \t Set the LED's RGB color.", .regex = "(led) (\\d*) (\\d*) (\\d*) (\\d*)", .funcPtr = command_set_led_single }, { .help = "led \t Set the color of multiple LEDs.", .regex = "(led) (\\d*)-(\\d*) (\\d*) (\\d*) (\\d*)", .funcPtr = command_set_led_multi }, { .help = "", .regex = ".*", .funcPtr = command_error }, { .regex = NULL } }; int command_error(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { printf("Command not found. Enter help to get a list of available commands.\n"); return 0; } int command_set_led_multi(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { int led, lede; int r, g, b; int is_temp; is_temp = strcmp(g_match_info_fetch(match_info, 1), "led"); led = atoi(g_match_info_fetch(match_info, 2)); lede = atoi(g_match_info_fetch(match_info, 3)); r = atoi(g_match_info_fetch(match_info, 4)); g = atoi(g_match_info_fetch(match_info, 5)); b = atoi(g_match_info_fetch(match_info, 6)); cmd_set_led(dev, is_temp ? BLOCK_META_RENDER : state->current_block, led, lede, r, g, b); return 0; } int command_set_led_single(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { int led; int r, g, b; int is_temp; is_temp = strcmp(g_match_info_fetch(match_info, 1), "led"); led = atoi(g_match_info_fetch(match_info, 2)); r = atoi(g_match_info_fetch(match_info, 3)); g = atoi(g_match_info_fetch(match_info, 4)); b = atoi(g_match_info_fetch(match_info, 5)); cmd_set_led(dev, is_temp ? BLOCK_META_RENDER : state->current_block, led, led, r, g, b); return 0; } int cmd_set_led(struct usb_dev_handle *dev, int block, int led, int lede, int r, int g, int b) { int i; if (led < 0 || led >= BLOCKSIZE || lede < 0 || lede >= BLOCKSIZE) { printf("ERROR: Valid LED numbers are 0 - %d.\n", BLOCKSIZE - 1); } else if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) { printf("ERROR: Valid colors are 0 - 255.\n"); } else { for (i = led; i <= lede; i++) { if (block == BLOCK_META_RENDER) set_templed(dev, block, i, r, g, b); else set_led(dev, block, i, r, g, b); } set_block(dev, block); } } int command_block(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { int block; block = atoi(g_match_info_fetch(match_info, 1)); if (block >= 0 && block < BLOCKCOUNT) { state->current_block = block; set_block(dev, block); } else { printf("ERROR: Valid block numbers are 0 - 11.\n"); } return 0; } int command_exit(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { state->run = 0; return 0; } int command_help(struct usb_dev_handle *dev, struct shell_state *state, GMatchInfo *match_info) { struct command_list_struct *check_cmd; printf("The following commands are available:\n"); for (check_cmd = command_list; check_cmd->funcPtr; check_cmd++) { printf(" %s\n", check_cmd->help ? check_cmd->help : check_cmd->regex); } return 0; } int main(int argc, char *argv[]) { GRegex *regex; GMatchInfo *match_info; struct usb_dev_handle *dev = NULL; struct usb_bus *bus; struct usb_device *devs; char iMan[256]; // Manufacturer name char iProd[256]; // Product name char cmd[256]; struct shell_state state; struct command_list_struct *check_cmd; state.run = 1; state.current_block = 0; usb_init(); usb_set_debug(3); usb_find_busses(); usb_find_devices(); for (bus = usb_busses; bus; bus = bus->next) { for (devs = bus->devices; devs; devs = devs->next) { if (devs->descriptor.idVendor == USBDEV_SHARED_VENDOR && devs->descriptor.idProduct == USBDEV_SHARED_PRODUCT) { dev = usb_open(devs); if (dev) { usb_get_string_simple(dev,devs->descriptor.iManufacturer, iMan, sizeof(iMan)); usb_get_string_simple(dev,devs->descriptor.iProduct, iProd, sizeof(iProd)); if (strcmp(iProd, PRODUCT_NAME) || strcmp(iMan, PRODUCT_MANFG)) { usb_close(dev); dev = NULL; } } break; } } if (dev) break; } if (dev) { printf("Opened device %s by %s!\n", iProd, iMan); set_block(dev, state.current_block); while (state.run) { printf("%02d$ ", state.current_block); fgets(cmd, sizeof(cmd), stdin); for (check_cmd = command_list; check_cmd->funcPtr; check_cmd++) { regex = g_regex_new(check_cmd->regex, G_REGEX_RAW, 0, NULL); if (g_regex_match(regex, cmd, 0, &match_info) && g_match_info_matches(match_info)) { check_cmd->funcPtr(dev, &state, match_info); g_regex_unref(regex); break; } g_regex_unref(regex); } } usb_close(dev); } return 0; } int set_block(struct usb_dev_handle *dev, int block) { if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CMD_SETBLOCK, block, 0, NULL, 0, 5000) < 0) return 0; return 1; } int set_led(struct usb_dev_handle *dev, int block, int led, int r, int g, int b) { int ret; if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CMD_EEWRITE, block * BLOCKSIZE * 3 + led * 3 + 0, r, NULL, 0, 5000) < 0) return 0; if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CMD_EEWRITE, block * BLOCKSIZE * 3 + led * 3 + 1, g, NULL, 0, 5000) < 0) return 0; if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CMD_EEWRITE, block * BLOCKSIZE * 3 + led * 3 + 2, b, NULL, 0, 5000) < 0) return 0; return 1; } int set_templed(struct usb_dev_handle *dev, int block, int led, int r, int g, int b) { int ret; if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CMD_SETLED, led + r*256 , g + b*256, NULL, 0, 5000) < 0) return 0; return 1; }