1 2 #ifndef ICOMS_H 3 4 /* An abstracted instrument serial and USB communication class. */ 5 6 /* 7 * Argyll Color Correction System 8 * 9 * Author: Graeme W. Gill 10 * Date: 2006/4/20 11 * 12 * Copyright 1996 - 2013 Graeme W. Gill 13 * All rights reserved. 14 * 15 * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :- 16 * see the License2.txt file for licencing details. 17 * 18 * Derived from serio.h 19 */ 20 21 /* Some MSWin specific stuff is in icoms, and used by usbio & hidio */ 22 #if defined (NT) 23 #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501 24 # if defined(_WIN32_WINNT) 25 # undef _WIN32_WINNT 26 # endif 27 # define _WIN32_WINNT 0x0501 28 #endif 29 #define WIN32_LEAN_AND_MEAN 30 #include <windows.h> 31 #endif 32 33 #if defined(UNIX_APPLE) 34 #include <IOKit/usb/IOUSBLib.h> 35 #endif 36 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 41 #undef QUIET_MEMCHECKERS /* #define to memset coms read buffers before reading */ 42 43 /* USB open/handling/buf workaround flags */ 44 typedef enum { 45 icomuf_none = 0x0000, 46 icomuf_detach = 0x0001, /* Attempt to detach from system driver */ 47 icomuf_no_open_clear = 0x0002, /* Don't send a clear_halt after opening the port */ 48 icomuf_reset_before_close = 0x0004, /* Reset port before closing it */ 49 /* ??? Could change to reset before open ??? */ 50 icomuf_resetep_before_read = 0x0008 /* Do a usb_resetep before each ep read */ 51 } icomuflags; 52 53 typedef enum { 54 icomt_unknown = 0x0000, 55 56 /* Category of device */ 57 icomt_instrument = 0x010000, /* Color measurement instrument (default) */ 58 icomt_3dlut = 0x020000, /* A 3D cLUT box */ 59 icomt_vtpg = 0x040000, /* A video test patern generator box */ 60 icomt_printer = 0x080000, /* A printing device */ 61 62 icomt_cat_any = 0x0f0000, /* Could be any device category */ 63 icomt_cat_mask = 0xff0000, /* Mask for device category */ 64 65 /* Type of underlying communication port */ 66 /* (fastserio driver will have icomt_serial and icomt_usb set) */ 67 icomt_serial = 0x000001, /* Serial port (i.e. has baud rate etc.) */ 68 icomt_usb = 0x000002, /* USB port */ 69 icomt_hid = 0x000004, /* HID USB port */ 70 icomt_bt = 0x000008, /* Bluetooth (non-serial) */ 71 72 icomt_port_mask = 0x0000ff, /* Mask for port type */ 73 74 /* Attributes */ 75 icomt_fastserial = 0x000100, /* Fast Serial (i.e. USB, fastserio, Bluetooth) */ 76 icomt_btserial = 0x000200, /* Bluetooth serial port */ 77 icomt_seriallike = 0x000400, /* Uses serial message methods, but */ 78 /* may not be actual icomt_serial. */ 79 80 icomt_attr_mask = 0x00ff00, /* Mask for port attributes */ 81 82 icomt_portattr_mask = icomt_port_mask | icomt_attr_mask, 83 84 icomt_portattr_all = icomt_portattr_mask /* Scan for all port types */ 85 86 87 } icom_type; 88 89 /* Status bits/return values */ 90 #define ICOM_OK 0x000000 /* No error */ 91 92 #define ICOM_NOTS 0x001000 /* Not supported */ 93 #define ICOM_SIZE 0x002000 /* Request/response size exceeded limits */ 94 #define ICOM_TO 0x004000 /* Timed out, but there may be bytes read/written */ 95 #define ICOM_SHORT 0x008000 /* No timeout but number of bytes wasn't read/written */ 96 #define ICOM_CANC 0x010000 /* Was cancelled */ 97 #define ICOM_SYS 0x020000 /* System error (ie. malloc, system call fail) */ 98 #define ICOM_VER 0x040000 /* Version error - need up to date kernel driver */ 99 100 #define ICOM_USBR 0x000100 /* Unspecified USB read error */ 101 #define ICOM_USBW 0x000200 /* Unspecified USB write error */ 102 #define ICOM_SERR 0x000400 /* Unspecified Serial read error */ 103 #define ICOM_SERW 0x000800 /* Unspecified Serial write error */ 104 105 #define ICOM_XRE 0x000040 /* Xmit shift reg empty */ 106 #define ICOM_XHE 0x000020 /* Xmit hold reg empty */ 107 #define ICOM_BRK 0x000010 /* Break detected */ 108 #define ICOM_FER 0x000008 /* Framing error */ 109 #define ICOM_PER 0x000004 /* Parity error */ 110 #define ICOM_OER 0x000002 /* Overun error */ 111 #define ICOM_DRY 0x000001 /* Recv data ready */ 112 113 typedef struct _icompath icompath; 114 typedef struct _icompaths icompaths; 115 typedef struct _icoms icoms; 116 117 #ifdef ENABLE_USB 118 119 struct usb_idevice; /* Forward declarations */ 120 struct hid_idevice; 121 122 /* Information about each end point */ 123 typedef struct { 124 int valid; /* Flag, nz if this endpoint is valid */ 125 int addr; /* Address of end point */ 126 int packetsize; /* The max packet size */ 127 int type; /* 2 = bulk, 3 = interrupt */ 128 int interface; /* interface number */ 129 #if defined(UNIX_APPLE) 130 int pipe; /* pipe number (1..N, OS X only) */ 131 #endif 132 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) 133 int fd; /* ep file descriptor */ 134 #endif 135 } usb_ep; 136 137 #define ICOM_EP_TYPE_BULK 2 138 #define ICOM_EP_TYPE_INTERRUPT 3 139 140 #include "usbio.h" 141 #include "hidio.h" 142 143 #endif /* ENABLE_USB */ 144 145 /* - - - - - - - - - - - - - - - - - - - - */ 146 147 /* Store information about a possible instrument communication path */ 148 /* (Note a path doesn't have a reference to icompaths or its' log) */ 149 struct _icompath { 150 devType itype; /* Type of device if known */ 151 char *name; /* instance description */ 152 153 icom_type dctype; /* Device and com. type */ 154 #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) 155 char *spath; /* Serial device path */ 156 #endif 157 #ifdef ENABLE_USB 158 int nep; /* Number of end points */ 159 unsigned int vid, pid; /* USB vendor and product id's */ 160 struct usb_idevice *usbd; /* USB port, NULL if not USB */ 161 struct hid_idevice *hidd; /* HID port, NULL if not HID */ 162 #endif /* ENABLE_USB */ 163 }; 164 165 extern icompath icomFakeDevice; /* Declare fake device */ 166 167 /* Device type specific list index */ 168 typedef enum { 169 dtix_combined = 0, /* Combined list */ 170 dtix_inst, /* Instrument */ 171 dtix_3dlut, 172 dtix_vtpg, 173 dtix_printer, 174 175 dtix_number /* Number of entries */ 176 } icom_dtix; 177 178 /* The available instrument communication paths */ 179 struct _icompaths { 180 a1log *log; /* Verbose, debuge & error logging */ 181 182 /* Combined and device category specific path lists (read only). */ 183 /* Paths may appear on more than one, if they are multi-function, */ 184 /* or the category can't be determined without opening them. */ 185 /* (dpaths[dtix_combined] is the owner of the icompath, */ 186 /* and all the others are only populated after discovery.) */ 187 icompath **dpaths[dtix_number]; /* Device paths if any */ 188 int ndpaths[dtix_number]; /* Number of device paths */ 189 190 /* Alias of dpaths[dtix_inst] for backwards compatibility, */ 191 /* only set after discovery. */ 192 icompath **paths; /* Device instrument if any */ 193 int npaths; /* Number of instrument paths */ 194 195 /* Re-discover and populate the available instrument list */ 196 /* return icom error */ 197 int (*refresh)(struct _icompaths *p); 198 199 /* Same as above, but just scan for selected types of devices and/or port types */ 200 int (*refresh_sel)(struct _icompaths *p, icom_type mask); 201 202 /* Return the instrument path corresponding to the port number, or NULL if out of range */ 203 icompath *(*get_path)( 204 struct _icompaths *p, 205 int port); /* Enumerated port number, 1..n */ 206 #define FAKE_DEVICE_PORT -98 /* Fake display & instrument */ 207 #define DEMO_DEVICE_PORT -99 /* Fake Demo instrument */ 208 209 /* Return the device path corresponding to the port number, or NULL if out of range */ 210 icompath *(*get_path_sel)( 211 struct _icompaths *p, 212 icom_type dctype, /* Device type list */ 213 int port); /* Enumerated port number, 1..n */ 214 215 /* Clear all the device paths */ 216 void (*clear)(struct _icompaths *p); 217 218 /* We're done */ 219 void (*del)(struct _icompaths *p); 220 221 /* ====== internal implementation ======= */ 222 223 #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) 224 /* Add a serial path to combined. path is copied. Return icom error */ 225 int (*add_serial)(struct _icompaths *p, char *name, char *spath, icom_type dctype); 226 #endif /* ENABLE_SERIAL */ 227 228 #ifdef ENABLE_USB 229 /* Add a usb path to combined. usbd is taken, others are copied. Return icom error */ 230 int (*add_usb)(struct _icompaths *p, char *name, unsigned int vid, unsigned int pid, 231 int nep, struct usb_idevice *usbd, devType itype); 232 233 /* Add an hid path to combined. hidd is taken, others are copied. Return icom error */ 234 int (*add_hid)(struct _icompaths *p, char *name, unsigned int vid, unsigned int pid, 235 int nep, struct hid_idevice *hidd, devType itype); 236 #endif /* ENABLE_USB */ 237 238 /* Delete the last combined path */ 239 void (*del_last_path)(struct _icompaths *p); 240 241 /* Return the last combined path */ 242 icompath *(*get_last_path)(struct _icompaths *p); 243 244 }; 245 246 /* Allocate an icom paths and set it to the list of available devices */ 247 /* Use g_log as argument for default logging. */ 248 /* Return NULL on error */ 249 icompaths *new_icompaths(a1log *log); 250 251 /* Same as above, but just scan for selected types of devices and/or port types */ 252 icompaths *new_icompaths_sel(a1log *log, icom_type mask); 253 254 255 /* - - - - - - - - - - - */ 256 /* Serial related stuff */ 257 258 /* Flow control */ 259 typedef enum { 260 fc_nc = 0, /* not configured/default */ 261 fc_None, 262 fc_XonXOff, 263 fc_Hardware, /* RTS CTS flow control */ 264 fc_HardwareDTR /* DTR DSR flow control */ 265 } flow_control; 266 267 /* baud rate available on all systems */ 268 typedef enum { 269 baud_nc = 0, /* Not Configured */ 270 baud_110 = 1, 271 baud_300 = 2, 272 baud_600 = 3, 273 baud_1200 = 4, 274 baud_2400 = 5, 275 baud_4800 = 6, 276 baud_9600 = 7, 277 baud_14400 = 8, 278 baud_19200 = 9, 279 baud_38400 = 10, 280 baud_57600 = 11, 281 baud_115200 = 12, 282 baud_921600 = 13 283 } baud_rate; 284 285 char *baud_rate_to_str(baud_rate br); 286 287 /* Possible parity */ 288 typedef enum { 289 parity_nc, 290 parity_none, 291 parity_odd, 292 parity_even 293 } parity; 294 295 /* Possible stop bits */ 296 typedef enum { 297 stop_nc, 298 stop_1, 299 stop_2 300 } stop_bits; 301 302 /* Possible word length */ 303 typedef enum { 304 length_nc, 305 length_5, 306 length_6, 307 length_7, 308 length_8 309 } word_length; 310 311 /* Interrupt callback type */ 312 typedef enum { 313 icomi_data_available /* Data is available to be read */ 314 } icom_int; 315 316 /* Cancelation token. */ 317 typedef struct _usb_cancelt usb_cancelt; 318 319 #ifdef ENABLE_USB 320 void usb_init_cancel(usb_cancelt *p); 321 void usb_uninit_cancel(usb_cancelt *p); 322 void usb_reinit_cancel(usb_cancelt *p); 323 #endif 324 325 struct _icoms { 326 /* Private: */ 327 328 /* Copy of some of icompath contents: */ 329 icom_type dctype; /* Device cat. and com. type */ 330 devType itype; /* Type of device if known */ 331 332 char *name; /* Device description */ 333 334 int is_open; /* Flag, NZ if this port is open */ 335 336 void *icntx; /* Optional instrument context */ 337 338 #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) 339 340 /* Serial port parameters */ 341 char *spath; /* Serial port path */ 342 #if defined (MSDOS) 343 unsigned short porta; /* Hardware port address */ 344 #endif 345 #if defined (NT) 346 HANDLE phandle; /* NT handle */ 347 #endif 348 #if defined (UNIX) 349 int fd; /* Unix file descriptor */ 350 #endif 351 flow_control fc; 352 baud_rate br; 353 parity py; 354 stop_bits sb; 355 word_length wl; 356 357 #endif /* ENABLE_SERIAL */ 358 359 #ifdef ENABLE_USB 360 361 /* USB port parameters */ 362 struct usb_idevice *usbd; /* USB port - copy of ppath->usbd */ 363 icomuflags uflags; /* Bug workaround flags */ 364 365 unsigned int vid, pid; /* USB vendor and product id's, used to distiguish instruments */ 366 int nconfig; /* Number of configurations */ 367 int config; /* Config this info applies to (always 1 ?) */ 368 int cconfig; /* Current configuration (0 or 1 ?) */ 369 int nifce; /* Number of interfaces */ 370 int nep; /* Number of end points */ 371 int wr_ep, rd_ep; /* Default end points to use for "serial" read/write */ 372 int rd_qa; /* Read quanta size */ 373 int ms_bytes; /* No. of Modem status bytes to strip from each read */ 374 int latmsec; /* Latency timeout in msec for modem status bytes */ 375 int (*interp_ms)(struct _icoms *p, unsigned char *msbytes); 376 /* return icom error from ms bytes, NULL if none */ 377 378 usb_ep ep[32]; /* Information about each end point for general usb i/o */ 379 380 /* Macro to access end point information */ 381 #define EPINFO(addr) ep[((addr >> 3) & 0x10) + (addr & 0x0f)] 382 383 /* HID port parameters */ 384 struct hid_idevice *hidd; /* HID port - copy of ppath->hidd */ 385 386 #endif /* ENABLE_USB */ 387 388 /* General parameters */ 389 int lserr; /* Last serial communication error code */ 390 a1log *log; /* Debug & Error log */ 391 int debug; /* legacy - Flag, nz to print instrument io info to stderr */ 392 393 /* Linked list to automate SIGKILL cleanup */ 394 struct _icoms *next; 395 396 /* Public: */ 397 398 /* Return the device category */ 399 /* (Returns bit flags) */ 400 icom_type (*dev_cat)(struct _icoms *p); 401 402 /* Return the communication port type */ 403 /* (Can use equality tests on return value for normal ports, */ 404 /* or bit flag for fastserio USB/serial port) */ 405 icom_type (*port_type)(struct _icoms *p); 406 407 /* Return the communication port attributes */ 408 /* (Returns bit flags) */ 409 icom_type (*port_attr)(struct _icoms *p); 410 411 #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) 412 /* Select the serial communications port and characteristics - extended version */ 413 /* return icom error */ 414 int (*set_ser_port_ex)( 415 struct _icoms *p, 416 flow_control fc, /* Flow control */ 417 baud_rate baud, 418 parity parity, 419 stop_bits stop_bits, 420 word_length word_length, 421 int delayms); /* Delay in ms after open */ 422 423 /* Select the serial communications port and characteristics */ 424 /* return icom error */ 425 int (*set_ser_port)( 426 struct _icoms *p, 427 flow_control fc, /* Flow control */ 428 baud_rate baud, 429 parity parity, 430 stop_bits stop_bits, 431 word_length word_length); 432 #endif /* ENABLE_SERIAL */ 433 434 #ifdef ENABLE_USB 435 /* Select the USB communications port and characteristics */ 436 /* return icom error */ 437 int (*set_usb_port)( 438 struct _icoms *p, 439 int config, /* Configuration */ 440 int wr_ep, /* "serial" write end point */ 441 int rd_ep, /* "serial" read end point */ 442 icomuflags usbflags, /* Any special handling flags */ 443 int retries, /* > 0 if we should retry set_configuration (100msec) */ 444 char **pnames /* List of process names to try and kill before opening */ 445 ); 446 447 /* Select the HID communications port and characteristics */ 448 /* return icom error */ 449 int (*set_hid_port)( 450 struct _icoms *p, 451 icomuflags usbflags, /* Any special handling flags */ 452 int retries, /* > 0 if we should retry set_configuration (100msec) */ 453 char **pnames /* List of process names to try and kill before opening */ 454 ); 455 #endif /* ENABLE_USB */ 456 457 /* Close the port */ 458 void (*close_port)(struct _icoms *p); 459 460 /* "Serial" write the characters in the buffer out */ 461 /* Data will be written up to the terminating nul. */ 462 /* return icom error */ 463 int (*write)( 464 struct _icoms *p, 465 char *buf, /* nul terminated unless nch > 0 */ 466 int nch, /* if > 0, number of characters to write, else nul terminated */ 467 double tout); /* Timeout in seconds */ 468 469 /* "Serial" read characters into the buffer */ 470 /* The returned data will be terminated by a nul. */ 471 /* return icom error */ 472 int (*read)( 473 struct _icoms *p, 474 char *buf, /* Buffer to store characters read */ 475 int bsize, /* Buffer size. Make this larger than chars required! */ 476 int *bread, /* Bytes read (not including forced '\000') */ 477 char *tc, /* Terminating characters, NULL for none or char count mode */ 478 int ntc, /* Number of terminating characters or char count needed. */ 479 double tout); /* Timeout in seconds */ 480 481 /* "Serial" write and read */ 482 /* return icom error */ 483 int (*write_read)( 484 struct _icoms *p, 485 char *wbuf, /* Write puffer */ 486 int nwch, /* if > 0, number of characters to write, else nul terminated */ 487 char *rbuf, /* Read buffer */ 488 int bsize, /* Buffer size. Make this larger than chars required! */ 489 int *bread, /* Bytes read (not including forced '\000') */ 490 char *tc, /* Terminating characers, NULL for none or char count mode */ 491 int ntc, /* Number of any terminating characters needed, or char count needed */ 492 double tout); /* Timeout in seconds */ 493 494 /* "Serial" write and read with read flush */ 495 /* return icom error */ 496 int (*write_read_ex)( 497 struct _icoms *p, 498 char *wbuf, /* Write puffer */ 499 int nwch, /* if > 0, number of characters to write, else nul terminated */ 500 char *rbuf, /* Read buffer */ 501 int bsize, /* Buffer size. Make this larger than chars required! */ 502 int *bread, /* Bytes read (not including forced '\000') */ 503 char *tc, /* Terminating characers, NULL for none or char count mode */ 504 int ntc, /* Number of any terminating characters needed, or char count needed */ 505 double tout, /* Timeout in seconds */ 506 int frbw); /* nz to Flush Read Before Write */ 507 508 /* For a USB device, do a control message */ 509 /* return icom error */ 510 int (*usb_control)(struct _icoms *p, 511 int requesttype, /* 8 bit request type (USB bmRequestType) */ 512 int request, /* 8 bit request code (USB bRequest) */ 513 int value, /* 16 bit value (USB wValue, sent little endian) */ 514 int index, /* 16 bit index (USB wIndex, sent little endian) */ 515 unsigned char *rwbuf, /* Read or write buffer */ 516 int rwsize, /* Bytes to read or write */ 517 double tout); /* Timeout in seconds */ 518 519 /* For a USB device, do a bulk or interrupt read from an end point */ 520 /* return icom error */ 521 int (*usb_read)(struct _icoms *p, 522 usb_cancelt *cancelt, /* Optionaly tokem that can be used to cancel */ 523 int ep, /* End point address */ 524 unsigned char *buf, /* Read buffer */ 525 int bsize, /* Bytes to read or write */ 526 int *bread, /* Bytes read */ 527 double tout); /* Timeout in seconds */ 528 529 /* For a USB device, do a bulk or interrupt write to an end point */ 530 /* return icom error */ 531 int (*usb_write)(struct _icoms *p, 532 usb_cancelt *cancelt, /* Optionaly tokem that can be used to cancel */ 533 int ep, /* End point address */ 534 unsigned char *wbuf, /* Write buffer */ 535 int wsize, /* Bytes to or write */ 536 int *bwritten, /* Bytes written */ 537 double tout); /* Timeout in seconds */ 538 539 /* Wait until a read/write in another thread has started. */ 540 /* return icom error */ 541 int (*usb_wait_io)(struct _icoms *p, 542 usb_cancelt *cantelt); /* Cancel handle */ 543 544 /* Cancel a read/write in another thread */ 545 /* return icom error */ 546 int (*usb_cancel_io)(struct _icoms *p, 547 usb_cancelt *cantelt); /* Cancel handle */ 548 549 /* Reset and end point toggle state to 0 */ 550 /* return icom error */ 551 int (*usb_resetep)(struct _icoms *p, 552 int ep); /* End point address */ 553 554 /* Clear an end point halt */ 555 /* return icom error */ 556 int (*usb_clearhalt)(struct _icoms *p, 557 int ep); /* End point address */ 558 559 /* For an HID device, read a message from the device. */ 560 /* return icom error */ 561 int (*hid_read)(struct _icoms *p, 562 unsigned char *buf, /* Read buffer */ 563 int bsize, /* Bytes to read or write */ 564 int *bread, /* Bytes read */ 565 double tout); /* Timeout in seconds */ 566 567 /* For an HID device, write a message to the device */ 568 /* return icom error */ 569 int (*hid_write)(struct _icoms *p, 570 unsigned char *wbuf, /* Write buffer */ 571 int wsize, /* Bytes to or write */ 572 int *bwritten, /* Bytes written */ 573 double tout); /* Timeout in seconds */ 574 575 /* Optional callback to client from device */ 576 /* Default implementation is a NOOP */ 577 int (*interrupt)(struct _icoms *p, 578 int icom_int); /* Interrupt cause */ 579 580 /* Destroy ourselves */ 581 void (*del)(struct _icoms *p); 582 583 }; 584 585 /* Constructor */ 586 extern icoms *new_icoms(icompath *ipath, a1log *log); 587 588 /* - - - - - - - - - - - - - - - - - - -- */ 589 /* Utilities */ 590 591 /* Convert control chars to ^[A-Z] notation in a string. */ 592 /* Returns a maximum of 1000 characters in static buffer. */ 593 char *icoms_fix(char *s); 594 595 /* Convert a limited binary buffer to a list of hex */ 596 char *icoms_tohex(unsigned char *s, int len); 597 598 /* Implementation declarations */ 599 600 #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) 601 602 int icoms_ser_write(icoms *p, char *wbuf, int nwch, double tout); 603 int icoms_ser_read(icoms *p, char *rbuf, int bsize, int *bread, 604 char *tc, int ntc, double tout); 605 606 #endif 607 608 #ifdef __cplusplus 609 } 610 #endif 611 612 #define ICOMS_H 613 #endif /* ICOMS_H */ 614