Advertisement
Guest User

lasershark fix

a guest
Aug 28th, 2015
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.60 KB | None | 0 0
  1. /*
  2. lasershark_stdin.c - Main host application to talk with Lasershark devices.
  3. Copyright (C) 2012 Jeffrey Nelson <nelsonjm@macpod.net>
  4.  
  5. This file is part of Lasershark's USB Host App.
  6.  
  7. Lasershark is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. Lasershark is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Lasershark. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <stdbool.h>
  27. #include <inttypes.h>
  28. #include <math.h>
  29. #include "libusb.h"
  30. #ifdef _WIN32
  31. #include <windows.h>
  32. #else
  33. #include <signal.h>
  34. #endif
  35. #include <time.h>
  36. #include "lasershark_lib.h"
  37. #include "getline_portable.h"
  38.  
  39.  
  40. #define LASERSHARK_VIN 0x1fc9
  41. #define LASERSHARK_PID 0x04d8
  42.  
  43. // Bulk timeout in ms
  44. #define BULK_TIMEOUT 100
  45.  
  46. int do_exit = 0;
  47.  
  48.  
  49. int lasershark_serialnum_len = 64;
  50. unsigned char lasershark_serialnum[64];
  51. uint32_t lasershark_fw_major_version = 0;
  52. uint32_t lasershark_fw_minor_version = 0;
  53.  
  54.  
  55. uint32_t lasershark_bulk_packet_sample_count;
  56. uint32_t lasershark_samp_element_count;
  57. uint32_t lasershark_max_ilda_rate;
  58. uint32_t lasershark_dac_min_val;
  59. uint32_t lasershark_dac_max_val;
  60.  
  61. uint32_t lasershark_ringbuffer_sample_count;
  62.  
  63. uint32_t lasershark_ilda_rate = 0;
  64.  
  65. struct libusb_device_handle *devh_ctl = NULL;
  66. struct libusb_device_handle *devh_data = NULL;
  67.  
  68.  
  69. uint64_t line_number = 0;
  70.  
  71. // Ugly hack to avoid using mingw to compile
  72. #define PACKED
  73. #pragma pack(push,1)
  74.  
  75. struct lasershark_sample
  76. {
  77.     unsigned short a    : 12;
  78.     unsigned short pad  : 2;
  79.     bool c  : 1;
  80.     bool intl_a : 1;
  81.     unsigned short b    : 16;
  82.     unsigned short x    : 16;
  83.     unsigned short y    : 16;
  84. } PACKED *samples;
  85.  
  86. #pragma pack(pop)
  87. #undef PACKED
  88.  
  89. uint32_t current_sample_entry = 0;
  90.  
  91.  
  92. #ifdef _WIN32
  93. // Handler function will be called on separate thread!
  94. static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
  95. {
  96.   switch (dwCtrlType)
  97.   {
  98.   case CTRL_C_EVENT: // Ctrl+C
  99.     break;
  100.   case CTRL_BREAK_EVENT: // Ctrl+Break
  101.     break;
  102.   case CTRL_CLOSE_EVENT: // Closing the console window
  103.     break;
  104.   case CTRL_LOGOFF_EVENT: // User logs off. Passed only to services!
  105.     break;
  106.   case CTRL_SHUTDOWN_EVENT: // System is shutting down. Passed only to services!
  107.     break;
  108.   }
  109.  
  110.   // Return TRUE if handled this message, further handler functions won't be called.
  111.   // Return FALSE to pass this message to further handlers until default handler calls ExitProcess().
  112.   return TRUE;
  113. }
  114.  
  115. #else
  116.  
  117. sigset_t mask, oldmask;
  118.  
  119. static void sig_hdlr(int signum)
  120. {
  121.     switch (signum)
  122.     {
  123.     case SIGINT:
  124.         printf("\nGot request to quit\n");
  125.         do_exit = 1;
  126.         break;
  127.     case SIGUSR1:
  128.         printf("sigusr1 caught\n");
  129.         do_exit = 1;
  130.         break;
  131.     default:
  132.         printf("what\n");
  133.     }
  134. }
  135. #endif
  136.  
  137. static bool inline send_samples(unsigned int sample_count)
  138. {
  139.     int r, actual;
  140.     do {
  141.         r = libusb_bulk_transfer(devh_data, (3 | LIBUSB_ENDPOINT_OUT), (unsigned char*)samples,
  142.                                  sizeof(struct lasershark_sample)*sample_count,
  143.                                  &actual, BULK_TIMEOUT);
  144.     } while (!do_exit && r == LIBUSB_ERROR_TIMEOUT);
  145.  
  146.     if (r < 0 && r != LIBUSB_ERROR_TIMEOUT) {
  147.         printf("Error sending sample packet: %s", libusb_error_name(r));
  148.         return false;
  149.     }
  150.  
  151.     return true;
  152. }
  153.  
  154.  
  155. // Sample integers are parsed this way vs scanf/etc for speed reasons.
  156. static bool inline parse_sample_integer(char* line, size_t len, unsigned int *pos, unsigned int *val)
  157. {
  158.     unsigned int orig_pos = *pos;
  159.     *val = 0;
  160.     while (*pos < len && line[*pos] >= '0' && line[*pos] <= '9') {
  161.         *val = 10*(*val) + line[*pos]-'0';
  162.         (*pos)++;
  163.         if (*val > lasershark_dac_max_val) {
  164.             return false;
  165.         }
  166.     }
  167.  
  168.     return orig_pos != *pos;
  169. }
  170.  
  171.  
  172. static bool handle_sample(char* line, size_t len)
  173. {
  174.     unsigned int x, y, a, b, c, intl_a;
  175.     unsigned int pos;
  176.  
  177.     // Lets make a giant if statement for fun
  178.     if (
  179.         len < 14 ||
  180.         (pos = 0, line[pos] != 's') || (pos++, line[pos] != '=') ||
  181.         (pos++, !parse_sample_integer(line, len, &pos, &x)) ||
  182.         pos >= len || line[pos] !=',' ||
  183.         (pos++, !parse_sample_integer(line, len, &pos, &y)) ||
  184.         pos >= len || line[pos] !=',' ||
  185.         (pos++, !parse_sample_integer(line, len, &pos, &a)) ||
  186.         pos >= len || line[pos] !=',' ||
  187.         (pos++, !parse_sample_integer(line, len, &pos, &b)) ||
  188.         pos >= len || line[pos] !=',' ||
  189.         (pos++, pos >= len) || (c=line[pos]-'0', c > 1) ||
  190.         (pos++, pos >= len) || line[pos] !=',' ||
  191.         (pos++, pos >= len) || (intl_a=line[pos]-'0', intl_a > 1)
  192.         ) {
  193.         printf("Received bad sample command\n");
  194.         return false;
  195.     }
  196.  
  197.     samples[current_sample_entry].x = x;
  198.     samples[current_sample_entry].y = y;
  199.     samples[current_sample_entry].a = a;
  200.     samples[current_sample_entry].b = b;
  201.     samples[current_sample_entry].c = c;
  202.     samples[current_sample_entry].intl_a = intl_a;
  203.  
  204.     current_sample_entry++;
  205.  
  206.     if (current_sample_entry == lasershark_bulk_packet_sample_count) {
  207.         current_sample_entry = 0;
  208.         return send_samples(lasershark_bulk_packet_sample_count);
  209.     }
  210.  
  211.     return true;
  212. }
  213.  
  214.  
  215. static bool handle_set_ilda_rate(char* line, size_t len)
  216. {
  217.     uint32_t rate = 0;
  218.     int rc;
  219.     if (1 != sscanf(line, "r=%u", &rate)) {
  220.         printf("Received malformated ilda rate command\n");
  221.         return false;
  222.     }
  223.  
  224.     if (rate == 0 || rate > lasershark_max_ilda_rate) {
  225.         printf("Received ilda rate outside acceptable range\n");
  226.     }
  227.  
  228.     lasershark_ilda_rate = rate;
  229.     rc = set_ilda_rate(devh_ctl, lasershark_ilda_rate);
  230.     if (rc != LASERSHARK_CMD_SUCCESS)
  231.     {
  232.         printf("setting ILDA rate failed\n");
  233.         return false;
  234.     }
  235.     printf("Setting ILDA rate worked: %u pps\n", lasershark_ilda_rate);
  236.  
  237.     return true;
  238. }
  239.  
  240.  
  241. static bool handle_set_output(char*line, size_t len)
  242. {
  243.     uint32_t enable = 0;
  244.     int rc;
  245.  
  246.     if (1 != sscanf(line, "e=%u", &enable)) {
  247.         printf("Received malfored enable command\n");
  248.         return false;
  249.     }
  250.  
  251.  
  252.     rc = set_output(devh_ctl, enable ? LASERSHARK_CMD_OUTPUT_ENABLE : LASERSHARK_CMD_OUTPUT_DISABLE);
  253.     if (rc != LASERSHARK_CMD_SUCCESS)
  254.     {
  255.         printf("Setting output failed\n");
  256.         return false;
  257.     }
  258.     if (enable) {
  259.         printf("Setting output output worked: %u\n", enable);
  260.     }
  261.     return true;
  262. }
  263.  
  264.  
  265. static bool handle_print(char* line, size_t len)
  266. {
  267.     bool rc = false;
  268.     if (len > 2 && line[1] == '=') {
  269.         printf("PRINT: %s", line+2);
  270.         rc = true;
  271.     }
  272.     return rc;
  273. }
  274.  
  275.  
  276. static bool handle_flush(char* line, size_t len)
  277. {
  278.     int rc;
  279.     uint32_t empty_samples;
  280.  
  281.     if (current_sample_entry != 0) {
  282.         if (!send_samples(current_sample_entry)) {
  283.             return false;
  284.         }
  285.     }
  286.  
  287.     current_sample_entry = 0;
  288.     printf("Flushing...\n");
  289.     while (1) {
  290.         rc = get_ringbuffer_empty_sample_count(devh_ctl, &empty_samples);
  291.         if (rc != LASERSHARK_CMD_SUCCESS)
  292.         {
  293.             printf("Getting ringbuffer empty sample count failed.\n");
  294.             return false;
  295.         }
  296.  
  297.         if (do_exit || empty_samples == lasershark_ringbuffer_sample_count) {
  298.             break;
  299.         }
  300.  
  301.     // TODO: Use something better than sleep
  302. #ifdef _WIN32
  303.         Sleep(1000);
  304. #else
  305.         sleep(1);
  306. #endif
  307.         printf("still flushing...\n");
  308.     }
  309.  
  310.     printf("Flush done\n");
  311.     return true;
  312. }
  313.  
  314.  
  315. static bool process_line(char* line, size_t len)
  316. {
  317.     bool rc = true;
  318.  
  319.     if (len < 2) { // Empty lines are not accepted
  320.         printf("Empty line encountered on line %" PRIu64 "\n", line_number);
  321.         return false;
  322.     }
  323.  
  324.     switch(line[0]) {
  325.     case 's':
  326.         rc = handle_sample(line, len);
  327.         break;
  328.     case 'f':
  329.         rc = handle_flush(line, len);
  330.         break;
  331.     case 'r':
  332.         rc = handle_set_ilda_rate(line, len);
  333.         break;
  334.     case 'e':
  335.         rc = handle_set_output(line, len);
  336.         break;
  337.     case 'p':
  338.         rc = handle_print(line, len);
  339.         break;
  340.     case '#': // Comment
  341.         break;
  342.     default:
  343.         printf("Unknown command received\n");
  344.         rc = false;
  345.     }
  346.  
  347.     if (!rc) {
  348.         printf("Error on line %" PRIu64 ": %s", line_number, line);
  349.     }
  350.  
  351.     line_number++;
  352.  
  353.     return rc;
  354. }
  355.  
  356. struct libusb_context *context;
  357. libusb_device **usbDevices;
  358.  
  359. int main (int argc, char *argv[])
  360. {
  361.     int rc;
  362.     uint32_t temp;
  363.  
  364. #ifndef _WIN32
  365.     struct sigaction sigact;
  366.  
  367.     sigact.sa_handler = sig_hdlr;
  368.     sigemptyset(&sigact.sa_mask);
  369.     sigact.sa_flags = 0;
  370.     sigaction(SIGINT, &sigact, NULL);
  371.     sigaction(SIGUSR1, &sigact, NULL);
  372. #endif
  373.  
  374.  
  375.     rc = libusb_init(context);
  376.     if (rc < 0)
  377.     {
  378.         fprintf(stderr, "Error initializing libusb: %d\n", /*libusb_error_name(rc)*/rc);
  379.         exit(1);
  380.     }
  381.  
  382.     struct libusb_device_descriptor desc;
  383.  
  384.     int numDevices = libusb_get_device_list(context, &usbDevices);
  385.     if(numDevices < 0)
  386.     {
  387.         libusb_free_device_list(usbDevices, 1);
  388.         goto out_post_release;
  389.     }
  390.  
  391.     devh_ctl = libusb_open_device_with_vid_pid(context, LASERSHARK_VIN, LASERSHARK_PID);
  392.     devh_data = libusb_open_device_with_vid_pid(context, LASERSHARK_VIN, LASERSHARK_PID);
  393.     if (!devh_ctl || !devh_data)
  394.     {
  395.         fprintf(stderr, "Error finding USB device, last error = %s\n", libusb_error_name(rc));
  396.         goto out_post_release;
  397.     }
  398.  
  399.     libusb_set_debug(context, 3);
  400.  
  401.     rc = libusb_claim_interface(devh_ctl, 0);
  402.     if (rc < 0)
  403.     {
  404.         fprintf(stderr, "Error claiming control interface: %d\n", /*libusb_error_name(rc)*/rc);
  405.         goto out_post_release;
  406.     }
  407.     rc = libusb_claim_interface(devh_data, 1);
  408.     if (rc < 0)
  409.     {
  410.         fprintf(stderr, "Error claiming data interface: %d\n", /*libusb_error_name(rc)*/rc);
  411.         libusb_release_interface(devh_ctl, 0);
  412.         goto out_post_release;
  413.     }
  414.  
  415.     rc = libusb_set_interface_alt_setting(devh_data, 1, 1);
  416.     if (rc < 0)
  417.     {
  418.         fprintf(stderr, "Error setting alternative (BULK) data interface: %d\n", /*libusb_error_name(rc)*/rc);
  419.         goto out;
  420.     }
  421.  
  422.  
  423.     //struct libusb_device_descriptor desc;
  424.  
  425.     rc = libusb_get_device_descriptor(libusb_get_device(devh_ctl), &desc);
  426.     if (rc < 0) {
  427.         fprintf(stderr, "Error obtaining device descriptor: %d\n", /*libusb_error_name(rc)*/rc);
  428.     }
  429.  
  430.     memset(lasershark_serialnum, lasershark_serialnum_len, 0);
  431.     rc = libusb_get_string_descriptor_ascii(devh_ctl, desc.iSerialNumber, lasershark_serialnum, lasershark_serialnum_len);
  432.     if (rc < 0) {
  433.         fprintf(stderr, "Error obtaining iSerialNumber: %d\n", /*libusb_error_name(rc)*/rc);
  434.     }
  435.     printf("iSerialNumber: %s\n", lasershark_serialnum);
  436.  
  437.  
  438.     rc = get_fw_major_version(devh_ctl, &lasershark_fw_major_version);
  439.     if (rc != LASERSHARK_CMD_SUCCESS)
  440.     {
  441.         printf("Getting FW Major version failed.\n");
  442.         goto out;
  443.     }
  444.     printf("Getting FW Major version: %d\n", lasershark_fw_major_version);
  445.  
  446.     rc = get_fw_minor_version(devh_ctl, &lasershark_fw_minor_version);
  447.     if (rc != LASERSHARK_CMD_SUCCESS)
  448.     {
  449.         printf("Getting FW Minor version failed.\n");
  450.         goto out;
  451.     }
  452.     printf("Getting FW Minor version: %d\n", lasershark_fw_minor_version);
  453.  
  454.     if (lasershark_fw_major_version != LASERSHARK_FW_MAJOR_VERSION ||
  455.             lasershark_fw_minor_version != LASERSHARK_FW_MINOR_VERSION) {
  456.         printf("Your FW is not capable of proper bulk transfers or clear commands. Please upgrade your firmware.\n");
  457.         goto out;
  458.     }
  459.  
  460.     printf("Clearing ringbuffer\n");
  461.     rc = clear_ringbuffer(devh_ctl);
  462.     if (rc != LASERSHARK_CMD_SUCCESS) {
  463.         printf("Clearing ringbuffer buffer failed.\n");
  464.         goto out;
  465.     }
  466.  
  467.  
  468.     rc = get_bulk_packet_sample_count(devh_ctl, &lasershark_bulk_packet_sample_count);
  469.     if (rc != LASERSHARK_CMD_SUCCESS)
  470.     {
  471.         printf("Getting bulk packet sample count failed\n");
  472.         goto out;
  473.     }
  474.     printf("Getting bulk packet sample count: %d\n", lasershark_bulk_packet_sample_count);
  475.  
  476.     samples = malloc(sizeof(struct lasershark_sample)*lasershark_bulk_packet_sample_count);
  477.     if (samples == NULL) {
  478.         printf("Could not allocate sample array.\n");
  479.         goto out;
  480.     }
  481.  
  482.     rc = get_max_ilda_rate(devh_ctl, &lasershark_max_ilda_rate);
  483.     if (rc != LASERSHARK_CMD_SUCCESS)
  484.     {
  485.         printf("Getting max ilda rate failed\n");
  486.         goto out;
  487.     }
  488.     printf("Getting max ilda rate: %u pps\n", lasershark_max_ilda_rate);
  489.  
  490.  
  491.     rc = get_dac_min(devh_ctl, &lasershark_dac_min_val);
  492.     if (rc != LASERSHARK_CMD_SUCCESS)
  493.     {
  494.         printf("Getting dac min failed\n");
  495.         goto out;
  496.     }
  497.     printf("Getting dac min: %d\n", lasershark_dac_min_val);
  498.  
  499.  
  500.     rc = get_dac_max(devh_ctl, &lasershark_dac_max_val);
  501.     if (rc != LASERSHARK_CMD_SUCCESS) {
  502.         printf("Getting dac max failed\n");
  503.         goto out;
  504.     }
  505.     printf("getting dac max: %d\n", lasershark_dac_max_val);
  506.  
  507.  
  508.     rc = get_ringbuffer_sample_count(devh_ctl, &lasershark_ringbuffer_sample_count);
  509.     if (rc != LASERSHARK_CMD_SUCCESS)
  510.     {
  511.         printf("Getting ringbuffer sample count\n");
  512.         goto out;
  513.     }
  514.     printf("Getting ringbuffer sample count: %d\n", lasershark_ringbuffer_sample_count);
  515.  
  516.  
  517.     rc = get_ringbuffer_empty_sample_count(devh_ctl, &temp);
  518.     if (rc != LASERSHARK_CMD_SUCCESS)
  519.     {
  520.         printf("Getting ringbuffer empty sample count failed.\n");
  521.     }
  522.     printf("Getting ringbuffer empty sample count: %d\n", temp);
  523.  
  524.     rc = set_output(devh_ctl, LASERSHARK_CMD_OUTPUT_DISABLE);
  525.     if (rc != LASERSHARK_CMD_SUCCESS)
  526.     {
  527.         printf("Disable output failed\n");
  528.         goto out;
  529.     }
  530.     printf("Disable output worked\n");
  531.  
  532.     ssize_t read;
  533.     size_t len = 256;
  534.  
  535.     char *line = malloc(len+1);
  536.     if (line == NULL) {
  537.         printf("Buffer malloc failed\n");
  538.         goto out;
  539.     }
  540.  
  541. #ifdef _WIN32
  542.     SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
  543. #else
  544.     sigemptyset (&mask);
  545.     sigaddset (&mask, SIGUSR1);
  546.  
  547.     sigprocmask (SIG_BLOCK, &mask, &oldmask);
  548. #endif
  549.  
  550.     printf("===Running===\n");
  551.  
  552.     if (-1 == (read = getline_portable(&line, &len, stdin)) || read < 1 || line[0] != 'r' || !process_line(line, read)) {
  553.         printf("First command did not specify ilda rate. Quitting.\n");
  554.     } else {
  555.         while (!do_exit && -1 != (read = getline_portable(&line, &len, stdin)) && process_line(line, read)) {
  556.             //sigsuspend (&oldmask);
  557.             //printf("Looping... (Must have recieved a signal, don't panic).\n");
  558.         }
  559.         //sigprocmask (SIG_UNBLOCK, &mask, NULL);
  560.     }
  561.  
  562.     printf("===Ending===\n");
  563.     rc = set_output(devh_ctl, LASERSHARK_CMD_OUTPUT_DISABLE);
  564.     if (rc != LASERSHARK_CMD_SUCCESS)
  565.     {
  566.         printf("Disable output failed\n");
  567.         goto out;
  568.     }
  569.     printf("Disable output worked\n");
  570.  
  571.     rc = get_ringbuffer_empty_sample_count(devh_ctl, &temp);
  572.     if (rc != LASERSHARK_CMD_SUCCESS)
  573.     {
  574.         printf("Getting ringbuffer empty sample count failed.\n");
  575.     }
  576.     if (lasershark_ringbuffer_sample_count-temp>0 || current_sample_entry) {
  577.         printf("Warning, not all samples displayed. Consider flushing before quitting.\n");
  578.         printf("\t%u not sent to Lasershark.\n", current_sample_entry);
  579.         temp = lasershark_ringbuffer_sample_count - temp;
  580.         printf("\t%u-%u = %u still in Lasershark's buffer.\n", lasershark_ringbuffer_sample_count, temp, lasershark_ringbuffer_sample_count-temp);
  581.     }
  582.  
  583.  
  584.     printf("Clearing ringbuffer\n");
  585.     rc = clear_ringbuffer(devh_ctl);
  586.     if (rc != LASERSHARK_CMD_SUCCESS) {
  587.         printf("Clearing ringbuffer buffer failed.\n");
  588.         goto out;
  589.     }
  590.  
  591.     printf("Quitting gracefully\n");
  592.  
  593. out:
  594.     libusb_release_interface(devh_ctl, 0);
  595.     libusb_release_interface(devh_data, 0);
  596.  
  597. out_post_release:
  598.     if (devh_ctl)
  599.     {
  600.         libusb_close(devh_ctl);
  601.     }
  602.     if (devh_data)
  603.     {
  604.         libusb_close(devh_data);
  605.     }
  606.  
  607.     libusb_free_device_list(usbDevices, 1);
  608.     libusb_exit(context);
  609.  
  610.     return rc;
  611. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement