static int vti_reset(CableHandle *h) { if(!hMap) return 0; if (vSendBuf) vSendBuf->start = vSendBuf->end = 0; else ticables_critical("vti_reset(): send buffer busted !\n"); if (vRecvBuf) vRecvBuf->start = vRecvBuf->end = 0; else ticables_critical("vti_reset(): receive buffer busted !\n"); return 0; }
static int vti_get(CableHandle *h, uint8_t *data, uint32_t len) { unsigned int i; tiTIME clk; if(!hMap) return 0; if(vRecvBuf) { /* Wait that the buffer has been filled */ for(i = 0; i < len; i++) { TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_READ_TIMEOUT; } while (vRecvBuf->start == vRecvBuf->end); /* And retrieve the data from the circular buffer */ data[i] = vRecvBuf->buf[vRecvBuf->start]; vRecvBuf->start = (vRecvBuf->start + 1) & (BUFSIZE-1); } } else { ticables_critical("vti_get(): receive buffer busted !\n"); } return 0; }
static int vti_put(CableHandle *h, uint8_t *data, uint32_t len) { unsigned int i; tiTIME clk; if(!hMap) return 0; if(vSendBuf) { for(i = 0; i < len; i++) { TO_START(clk); do { if (TO_ELAPSED(clk, h->timeout)) return ERR_WRITE_TIMEOUT; } while (((vSendBuf->end + 1) & (BUFSIZE-1)) == vSendBuf->start); vSendBuf->buf[vSendBuf->end] = data[i]; vSendBuf->end = (vSendBuf->end + 1) & (BUFSIZE-1); } } else { ticables_critical("vti_put(): send buffer busted !\n"); } return 0; }
/** * ticables_get_usb_devices: * @array: address of a NULL-terminated allocated array of integers (PIDs). * @length: number of detected USB devices. * * Returns the list of detected USB PIDs. Note that list is in the * same order as PORT#x. * The array must be freed when no longer used. * * Return value: 0 if successful, an error code otherwise. **/ TIEXPORT1 int TICALL ticables_get_usb_devices(int **list, int *len) { if (list != NULL) { #if defined(__WIN32__) || (defined(HAVE_LIBUSB) || defined(HAVE_LIBUSB_1_0)) int i, *p; int ret = 0; ret = usb_probe_devices(list); if(ret) { *list = calloc(1, sizeof(int)); if(len) *len = 0; return ret; } for(p = *list, i = 0; *p; p++, i++); //printf("%i: %04x\n", i, (*list)[i]); if(len) *len = i; #else *list = calloc(1, sizeof(int)); if(len) *len = 0; #endif } else { ticables_critical("%s: list is NULL", __FUNCTION__); return -1; } return 0; }
static void tigl_get_product(char * string, size_t maxlen, struct libusb_device *dev) { libusb_device_handle *han; int ret; struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); string[0] = 0; if (r < 0) { ticables_critical("failed to get device descriptor"); } if (desc.iProduct) { if (!libusb_open(dev, &han)) { ret = libusb_get_string_descriptor_ascii(han, desc.iProduct, (unsigned char *) string, maxlen); libusb_close(han); if (ret <= 0) { ticables_warning("libusb_get_string_descriptor_ascii (%s).\n", tigl_strerror(ret)); } } // else do nothing. } }
static int vti_check(CableHandle *h, int *status) { if(!hMap) return 0; if(vRecvBuf) { *status = !(vRecvBuf->start == vRecvBuf->end); } else { ticables_critical("vti_check(): receive buffer busted !\n"); } return 0; }
/** * ticables_probing_finish: * @result: address of an array of integers. * * Free the array created by #ticables_probing_do. * * Return value: always 0. **/ TIEXPORT1 int TICALL ticables_probing_finish(int ***result) { int i; if (result != NULL && *result != NULL) { for(i = CABLE_GRY; i <= CABLE_TIE; i++) { free((*result)[i]); (*result)[i] = NULL; } free(*result); *result = NULL; } else { ticables_critical("%s(NULL)", __FUNCTION__); } return 0; }
int log_hex_start(void) { int ret; ofn = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S, LOG_DIR, G_DIR_SEPARATOR_S, HEX_FILE, NULL); logfile = fopen(ofn, "wt"); if (logfile != NULL) { fprintf(logfile, "TiCables-2 data logger\n"); // needed by log_dbus.c fprintf(logfile, "Version %s\n", ticables_version_get()); fprintf(logfile, "\n"); ret = 0; } else { ticables_critical("Unable to open %s for logging.\n", ofn); ret = 1; } return ret; }
static int vti_open(CableHandle *h) { int i; char vLinkFileName[32]; char name[32]; HANDLE hVLinkFileMap = NULL; HANDLE Handle; ATOM a; /* Get an handle on the VTi window */ otherWnd = FindWindow("TEmuWnd", NULL); if (!otherWnd) return ERR_VTI_FINDWINDOW; /* Get the current DLL handle */ Handle = GetModuleHandle("libticables2.dll"); if(!Handle) Handle = GetModuleHandle("libticables2-5.dll"); if (!Handle) { ticables_critical(_("FATAL ERROR: unable to get an handle on the ticables-2 library.")); ticables_critical(_("Did you rename the library ?!")); return ERR_NO_LIBRARY; } /* Create a file mapping handle for the 'lib->VTi' communication channel */ for (i = 0; ; i++) { sprintf(vLinkFileName, "Virtual Link %d", i); hVLinkFileMap = CreateFileMapping((HANDLE) - 1, NULL, PAGE_READWRITE, 0, sizeof(LinkBuffer), vLinkFileName); if (GetLastError() != ERROR_ALREADY_EXISTS) break; } ticables_info("Virtual Link L->V %i", i); vSendBuf = (LinkBuffer *)MapViewOfFile(hVLinkFileMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkBuffer)); // Inform VTI of our virtual link so that it can enable it. It should return // its virtual link name in a message. SendMessage(otherWnd, WM_HELLO, 0, (LPARAM) Handle); /* Retrieve the VTi virtual link name */ //b = GetMessage(&msg, NULL, WM_HELLO, WM_SEND_BUFFER); //WaitMessage(); // Waits VTi answer /* Create a file mapping handle for the 'Vti->lib' communication channel */ ticables_info("Virtual Link V->L %i", i-1); sprintf(name, "Virtual Link %d", i - 1); hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name); if (hMap) { ticables_info(_("Opened %s"), name); vRecvBuf = (LinkBuffer *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkBuffer)); } else return ERR_VTI_OPENFILEMAPPING; /* Send to VTi the name of our virtual link. VTi should open it (lib -> Vti) */ a = GlobalAddAtom(vLinkFileName); SendMessage(otherWnd, WM_SEND_BUFFER, 0, (LPARAM) a); GlobalDeleteAtom(a); /* Enable linking (check the VTi's Virtual Link|Enable cable link' item) */ if (otherWnd) SendMessage(otherWnd, WM_ENABLE_LINK, 0, 0); vSendBuf->start = vSendBuf->end = 0; vRecvBuf->start = vRecvBuf->end = 0; return 0; }
/** * ticables_probing_do: * @result: address of an array of integers to put the result. * @timeout: timeout to set during probing * @method: defines which link cables you want to search for. * * Returns cables which have been detected. All cables should be closed before ! * The array is like a matrix which contains 5 columns (PORT_0 to PORT_4) and * 7 lines (CABLE_GRY to CABLE_USB). * The array must be freed by #ticables_probing_finish when no longer used. * * Return value: 0 if successful, ERR_NO_CABLE if no cables found. **/ TIEXPORT1 int TICALL ticables_probing_do(int ***result, int timeout, ProbingMethod method) { CablePort port; CableModel model; int **array; int found = 0; if (result == NULL) { ticables_critical("%s: result is NULL", __FUNCTION__); return ERR_PROBE_FAILED; } ticables_info(_("Link cable probing:")); array = (int **)calloc(CABLE_MAX + 1, sizeof(int *)); for(model = CABLE_NUL; model <= CABLE_MAX; model++) array[model] = (int *)calloc(5, sizeof(int)); // look for USB devices (faster) if(method & PROBE_USB) { int *list, n, i; ticables_get_usb_devices(&list, &n); for(i = 0; i < n; i++) { port = i+1; if(list[i] == PID_TIGLUSB) array[CABLE_SLV][port] = !0; if(list[i]) array[CABLE_USB][port] = !0; if(list[i]) found = !0; } } if((method & PROBE_FIRST) && found) { *result = array; return found ? 0 : ERR_NO_CABLE; } // look for DBUS devices (slower) if(method & PROBE_DBUS) { for(model = CABLE_GRY; model <= CABLE_PAR; model++) { for(port = PORT_1; port <= PORT_4; port++) { CableHandle* handle; int err, ret; handle = ticables_handle_new(model, port); if(handle) { ticables_options_set_timeout(handle, timeout); err = ticables_cable_probe(handle, &ret); array[model][port] = (ret && !err) ? 1: 0; if(array[model][port]) found = !0; if(found && (method & PROBE_FIRST)) { ticables_handle_del(handle); break; } } ticables_handle_del(handle); } } } *result = array; return found ? 0 : ERR_NO_CABLE; }
/** * ticables_error_get: * @number: error number (see error.h for list). * @message: a newly GLib allocated string which contains corresponding error *message. * * Attempt to match the message corresponding to the error number. The returned * string must be freed when no longer needed. * The error message has the following format: * - 1: the error message * - 2: the cause(s), explanations on how to fix it * - 3: the error returned by the system * * Return value: 0 if error has been caught, the error number otherwise (propagation). **/ TIEXPORT1 int TICALL ticables_error_get(CableError number, char **message) { char *tmp; if (message == NULL) { ticables_critical("ticables_error_get(NULL)\n"); return number; } switch(number) { case ERR_BUSY: *message = g_strconcat( _("Msg: link cable is busy."), "\n", _("Cause: a transfer is in progress."), NULL); break; case ERR_ROOT: *message = g_strconcat( _("Msg: unable to use parallel/serial port: access refused."), "\n", _("Cause: you are not running program as root or setuid root."), NULL); break; case ERR_TTDEV: *message = g_strconcat( _("Msg: unable to use serial (/dev/ttySx) device."), "\n", _("Cause: the /dev/ttySx node doesn't exist or you don't have required permissions. " \ "How to grant permission to devices to the user depends on the " \ "distribution, it may involve adding the user to a group such " \ "as 'dialout' or 'uucp'. This can be done by editing /etc/group " \ "and add the username after the ':'. Example: dialout:x:20:romain " \ "" ), NULL); break; case ERR_PPDEV: *message = g_strconcat( _("Msg: unable to use parport (/dev/parportX) device."), "\n", _("Cause: the /dev/parportX node doesn't exist or you don't have required permissions. " "How to grant permission to devices to the user depends on the " \ "distribution, it may involve adding the user to a group such " \ "as 'lp'. This can be done by editing /etc/group " \ "and add the username after the ':'. Example: lp:x:7:romain " \ "" ), NULL); break; case ERR_USBFS: *message = g_strconcat( _("Msg: unable to use USB pseudo file system."), "\n", _("Cause: the USB filesystem is not mounted or " \ "cannot access USB device because current user doesn't have the necessary " \ "permissions. How to grant permission to devices to the user depends on the " \ "distribution; it may involve adding udev and/or pam_console configuration " \ "files, and you may in addition have to add your user to a group such " \ "as 'usb' or set-up libusb mounting parameters." \ "If packages of TiLP and its libraries for your distribution exist, " \ "it is recommended to use those, as everything which can be configured " \ "automatically will be set up for you. Otherwise, manual setup steps, if any, are " \ "explained in the CONFIG file shipped with the ticables2 library. " \ "" ), NULL); break; case ERR_ILLEGAL_ARG: *message = g_strconcat( _("Msg: illegal operation or argument."), "\n", _("Cause: the program which uses this library is buggy. Fire-up the developer!"), NULL); break; case ERR_DHA_NOT_FOUND: *message = g_strconcat( _("Msg: DhaHelper driver and/or library not found."), "\n", _("Cause: the driver may have been not started yet; it may have been uninstalled; the library has been installed without administrator privileges."), NULL); break; case ERR_RWP_NOT_FOUND: *message = g_strconcat( _("Msg: RwPorts driver and/or library not found."), "\n", _("Cause: the driver may have been not started yet; it may have been uninstalled; the library has been installed without administrator privileges."), NULL); break; case ERR_WRITE_ERROR: *message = g_strconcat( _("Msg: error occured while writing to the device."), NULL); break; case ERR_WRITE_TIMEOUT: *message = g_strconcat( _("Msg: timeout occured while writing to the device."), "\n", _("Cause: check that link cable is plugged and/or the calculator is ready."), NULL); break; case ERR_READ_ERROR: *message = g_strconcat( _("Msg: error occured while reading from the device."), NULL); break; case ERR_READ_TIMEOUT: *message = g_strconcat( _("Msg: timeout occured while reading from the device."), "\n", _("Cause: check that link cable is plugged and/or the calculator is ready."), NULL); break; case ERR_PROBE_FAILED: *message = g_strconcat( _("Msg: the probing of device failed."), "\n", _("Cause: internal error. If you get it, this is a bug!"), NULL); break; case ERR_GRY_CREATEFILE: case ERR_GRY_SETUPCOMM: case ERR_GRY_GETCOMMSTATE: case ERR_GRY_SETCOMMSTATE: case ERR_GRY_GETCOMMTIMEOUT: case ERR_GRY_SETCOMMTIMEOUT: case ERR_GRY_PURGECOMM: case ERR_GRY_SETCOMMMASK: *message = g_strconcat( _("Msg: unable to open serial port."), "\n", _("Cause: check that device is not used/locked by another application."), NULL); break; case ERR_VTI_FINDWINDOW: case ERR_VTI_OPENFILEMAPPING: case ERR_VTI_MAPVIEWOFFILE: *message = g_strconcat( _("Msg: failed to get VTI handle."), "\n", _("Cause: VTI may not be running. VTI must be launched before."), NULL); break; case ERR_VTI_IPCKEY: case ERR_VTI_SHMGET: case ERR_VTI_SHMAT: case ERR_VTI_SHMDT: case ERR_VTI_SHMCTL: *message = g_strconcat( _("Msg: unable to get a unique IPC (Inter Process Communication) key."), "\n", _("Cause: check that you have enough resources for allocating a shared memory segment."), NULL); break; case ERR_TIE_OPEN: case ERR_TIE_CLOSE: *message = g_strconcat( _("Msg: unable to open/close pipes for virtual linking."), "\n", _("Cause: check that you have permissions to create a pipe in the /tmp directory."), NULL); break; case ERR_TTY_OPEN: case ERR_GRY_OPEN: *message = g_strconcat( _("Msg: unable to open serial device."), "\n", _("Cause: check that you have permissions on /dev/ttySx device. Check that device is not locked."), NULL); break; case ERR_TTY_IOCTL: case ERR_GRY_IOCTL: *message = g_strconcat( _("Msg: unable to issue a specific command on serial device."), "\n", _("Cause: check that you have permissions on /dev/ttySx device. Check that device is not locked."), NULL); break; case ERR_PPT_OPEN: *message = g_strconcat( _("Msg: unable to open parallel device."), "\n", _("Cause: check that you have permissions on /dev/parportX device. Check that device is not locked."), NULL); break; case ERR_PPT_IOCTL: *message = g_strconcat( _("Msg: unable to issue a specific command on parallel device."), "\n", _("Cause: check that you have permissions on /dev/parportX device. Check that device is not locked."), NULL); break; case ERR_LIBUSBWIN32_NOT_PRESENT: *message = g_strconcat( _("Msg: unable to find the libusb-win32 driver."), "\n", _("Cause: the driver is not present and/or installed."), NULL); break; case ERR_LIBUSB_OPEN: case ERR_LIBUSB_CLAIM: case ERR_LIBUSB_CONFIG: *message = g_strconcat( _("Msg: failed to open the USB device."), "\n", _("Cause: Check that the USB cable is plugged in and that the calculator is turned ON! Also, check libusb and usbfs for valid permissions."), NULL); break; case ERR_LIBUSB_RESET: *message = g_strconcat( _("Msg: unable to reset USB device."), "\n", _("Cause: Check that cable is connected or not stalled. Try to unplug/plug it."), NULL); break; case ERR_NOT_OPEN: *message = g_strconcat( _("Msg: attempting to use a cable which has not been open before."), "\n", _("Cause: Internal error."), NULL); break; case ERR_NO_CABLE: *message = g_strconcat( _("Msg: no cable found."), "\n", _("Cause: probing failed or invalid parameters."), NULL); break; case ERR_NO_LIBRARY: *message = g_strconcat( _("Msg: DLL not found."), "\n", _("Cause: maybe you renamed the DLL ?"), NULL); break; default: // propagate error code return number; } #ifndef __WIN32__ if (errno != 0) { gchar *str; tmp = *message; str = g_strdup_printf(" (errno = %i)", errno); *message = g_strconcat(tmp, "\n", "System: ", strerror(errno), str, "\n", NULL); g_free(tmp); g_free(str); } #else if (GetLastError()) { LPVOID lpMsgBuf; gchar *str; tmp = *message; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); str = g_strdup_printf("(%li) %s", (long)GetLastError, (char *)lpMsgBuf); *message = g_strconcat(tmp, "\n", "System: ", str, NULL); g_free(tmp); g_free(str); } #endif return 0; }