X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=libaltos%2Flibaltos.c;h=2a41ef80159e1813f7573672fe049a69d1c78a65;hp=6e884c80ea145eeb576955d7d703f6a43f2d94af;hb=d029acad6a992be9b7b4498e70605f8a1e1a4ef6;hpb=d83587c3c66b730cc54ca153714eee520ee40b2c diff --git a/libaltos/libaltos.c b/libaltos/libaltos.c index 6e884c80..2a41ef80 100644 --- a/libaltos/libaltos.c +++ b/libaltos/libaltos.c @@ -116,7 +116,6 @@ altos_open(struct altos_device *device) return NULL; } - printf ("open\n"); // altos_set_last_error(12, "yeah yeah, failed again"); // free(file); // return NULL; @@ -479,26 +478,26 @@ usb_tty(char *sys) return tty; } - /* Check for ttyACMx style names + /* Check for tty/ttyACMx style names */ - ntty = scandir(endpoint_full, &namelist, + tty_dir = cc_fullname(endpoint_full, "tty"); + ntty = scandir(tty_dir, &namelist, dir_filter_tty, alphasort); + free (tty_dir); if (ntty > 0) { - free(endpoint_full); tty = cc_fullname("/dev", namelist[0]->d_name); + free(endpoint_full); free(namelist); return tty; } - /* Check for tty/ttyACMx style names + /* Check for ttyACMx style names */ - tty_dir = cc_fullname(endpoint_full, "tty"); - free(endpoint_full); - ntty = scandir(tty_dir, &namelist, + ntty = scandir(endpoint_full, &namelist, dir_filter_tty, alphasort); - free (tty_dir); + free(endpoint_full); if (ntty > 0) { tty = cc_fullname("/dev", namelist[0]->d_name); free(namelist); @@ -607,12 +606,17 @@ altos_list_start(void) return devs; } +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + return altos_list_start(); +} + int altos_list_next(struct altos_list *list, struct altos_device *device) { struct altos_usbdev *dev; if (list->current >= list->ndev) { - printf ("end\n"); return 0; } dev = list->dev[list->current]; @@ -787,6 +791,7 @@ no_file: struct altos_list { io_iterator_t iterator; + int ftdi; }; static int @@ -844,8 +849,21 @@ altos_list_start(void) int i; ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); - if (ret != kIOReturnSuccess) + if (ret != kIOReturnSuccess) { + free(list); return NULL; + } + list->ftdi = 0; + return list; +} + +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + struct altos_list *list = altos_list_start(); + + if (list) + list->ftdi = 1; return list; } @@ -863,10 +881,15 @@ altos_list_next(struct altos_list *list, struct altos_device *device) if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || !get_number (object, CFSTR(kUSBProductID), &device->product)) continue; - if (device->vendor != 0xfffe) - continue; - if (device->product < 0x000a || 0x0013 < device->product) - continue; + if (list->ftdi) { + if (device->vendor != 0x0403) + continue; + } else { + if (device->vendor != 0xfffe) + continue; + if (device->product < 0x000a || 0x0013 < device->product) + continue; + } if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) && get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) && get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { @@ -937,6 +960,7 @@ altos_bt_open(struct altos_bt_device *device) struct altos_list { HDEVINFO dev_info; int index; + int ftdi; }; #define USB_BUF_SIZE 64 @@ -953,6 +977,24 @@ struct altos_file { OVERLAPPED ov_write; }; +#include + +static void +log_message(char *fmt, ...) +{ + static FILE *log = NULL; + va_list a; + + if (!log) + log = fopen("\\temp\\altos.txt", "w"); + if (log) { + va_start(a, fmt); + vfprintf(log, fmt, a); + va_end(a); + fflush(log); + } +} + static void _altos_set_last_windows_error(char *file, int line) { @@ -966,7 +1008,7 @@ _altos_set_last_windows_error(char *file, int line) sizeof (message) / sizeof (TCHAR), NULL); if (error != ERROR_SUCCESS) - printf ("%s:%d %s\n", file, line, message); + log_message ("%s:%d %s\n", file, line, message); altos_set_last_error(error, message); } @@ -987,6 +1029,26 @@ altos_list_start(void) return NULL; } list->index = 0; + list->ftdi = 0; + return list; +} + +PUBLIC struct altos_list * +altos_ftdi_list_start(void) +{ + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); + free(list); + return NULL; + } + list->index = 0; + list->ftdi = 1; return list; } @@ -1017,28 +1079,32 @@ altos_list_next(struct altos_list *list, struct altos_device *device) KEY_READ); if (dev_key == INVALID_HANDLE_VALUE) { altos_set_last_windows_error(); - printf("cannot open device registry key\n"); continue; } - /* Fetch symbolic name for this device and parse out - * the vid/pid/serial info */ - symbolic_len = sizeof(symbolic); - result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, - symbolic, &symbolic_len); - if (result != 0) { - altos_set_last_windows_error(); - printf("cannot find SymbolicName value\n"); - RegCloseKey(dev_key); - continue; + if (list->ftdi) { + vid = 0x0403; + pid = 0x6015; + serial = 0; + } else { + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, + symbolic, &symbolic_len); + if (result != 0) { + altos_set_last_windows_error(); + RegCloseKey(dev_key); + continue; + } + vid = pid = serial = 0; + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + "%d", &serial); } - vid = pid = serial = 0; - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, - "%04X", &vid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, - "%04X", &pid); - sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, - "%d", &serial); /* Fetch the com port name */ port_len = sizeof (port); @@ -1047,7 +1113,6 @@ altos_list_next(struct altos_list *list, struct altos_device *device) RegCloseKey(dev_key); if (result != 0) { altos_set_last_windows_error(); - printf("failed to get PortName\n"); continue; } @@ -1063,7 +1128,6 @@ altos_list_next(struct altos_list *list, struct altos_device *device) &friendlyname_len)) { altos_set_last_windows_error(); - printf("Failed to get friendlyname\n"); continue; } device->vendor = vid; @@ -1075,10 +1139,8 @@ altos_list_next(struct altos_list *list, struct altos_device *device) return 1; } result = GetLastError(); - if (result != ERROR_NO_MORE_ITEMS) { + if (result != ERROR_NO_MORE_ITEMS) altos_set_last_windows_error(); - printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); - } return 0; } @@ -1137,6 +1199,7 @@ altos_wait_read(struct altos_file *file, int timeout) return LIBALTOS_TIMEOUT; break; default: + altos_set_last_windows_error(); return LIBALTOS_ERROR; } return LIBALTOS_SUCCESS; @@ -1174,7 +1237,6 @@ altos_flush(struct altos_file *file) if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { if (GetLastError() != ERROR_IO_PENDING) { altos_set_last_windows_error(); - printf ("\tflush write error\n"); return LIBALTOS_ERROR; } ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE); @@ -1182,13 +1244,11 @@ altos_flush(struct altos_file *file) case WAIT_OBJECT_0: if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) { altos_set_last_windows_error(); - printf ("\tflush result error\n"); return LIBALTOS_ERROR; } break; default: altos_set_last_windows_error(); - printf ("\tflush wait error\n"); return LIBALTOS_ERROR; } } @@ -1199,6 +1259,60 @@ altos_flush(struct altos_file *file) return LIBALTOS_SUCCESS; } +static HANDLE +open_serial(char *full_name) +{ + HANDLE handle; + DCB dcb; + + handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + + if (handle == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); + return INVALID_HANDLE_VALUE; + } + + if (!GetCommState(handle, &dcb)) { + altos_set_last_windows_error(); + CloseHandle(handle); + return INVALID_HANDLE_VALUE; + } + dcb.BaudRate = CBR_9600; + dcb.fBinary = TRUE; + dcb.fParity = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fDsrSensitivity = FALSE; + dcb.fTXContinueOnXoff = FALSE; + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + dcb.fErrorChar = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fAbortOnError = FALSE; + dcb.XonLim = 10; + dcb.XoffLim = 10; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + dcb.XonChar = 17; + dcb.XoffChar = 19; +#if 0 + dcb.ErrorChar = 0; + dcb.EofChar = 0; + dcb.EvtChar = 0; +#endif + if (!SetCommState(handle, &dcb)) { + altos_set_last_windows_error(); + CloseHandle(handle); + return INVALID_HANDLE_VALUE; + } + return handle; +} + PUBLIC struct altos_file * altos_open(struct altos_device *device) { @@ -1211,17 +1325,22 @@ altos_open(struct altos_device *device) strcpy(full_name, "\\\\.\\"); strcat(full_name, device->path); - file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); + + file->handle = open_serial(full_name); if (file->handle == INVALID_HANDLE_VALUE) { - altos_set_last_windows_error(); - printf ("cannot open %s\n", full_name); free(file); return NULL; } - file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + /* The FTDI driver doesn't appear to work right unless you open it twice */ + if (device->vendor == 0x0403) { + CloseHandle(file->handle); + file->handle = open_serial(full_name); + if (file->handle == INVALID_HANDLE_VALUE) { + free(file); + return NULL; + } + } timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; @@ -1230,6 +1349,9 @@ altos_open(struct altos_device *device) timeouts.WriteTotalTimeoutConstant = 0; SetCommTimeouts(file->handle, &timeouts); + file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + return file; } @@ -1274,8 +1396,10 @@ altos_getchar(struct altos_file *file, int timeout) { int ret; while (file->in_read == file->in_used) { - if (file->handle == INVALID_HANDLE_VALUE) + if (file->handle == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } ret = altos_fill(file, timeout); if (ret) return ret;