C Linux
From Cricut Hacking Wiki
Code examples
Current alpha version of Linux sources on SourceForge at http://licut.sourceforge.net
This Linux-specific code snippet opens /dev/ttyUSB0 and sets the rate to 200kbps and returns a handle for use by read() and write():
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <termios.h> #include <linux/serial.h> int open_port_200kbps() { int handle = open( "/dev/ttyUSB0", O_RDWR | O_NOCTTY ); if (handle <= 0) { printf( "Failed to open %s - %d (%s)\n", "/dev/ttyUSB0", errno, strerror(errno) ); return -1; } struct termios oldtio,newtio; tcgetattr( handle, &oldtio ); /* save current port settings */ bzero( &newtio, sizeof(newtio) ); // Set custom rate to 200kbps 8N1 - we're actually sending 8N2 but get 8N1 back newtio.c_cflag = B38400 | /*CRTSCTS |*/ CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 5; /* blocking read until 5 chars received */ tcflush( handle, TCIFLUSH ); tcsetattr( handle, TCSANOW, &newtio ); // Now use TIOCSSERIAL ioctl to set custom divisor // FTDI uses base_baud 24000000 so in theory a divisor // of 120 should give us 200000 baud... struct serial_struct sio; // From /usr/include/linux/serial.h int ioctl_res = ioctl( handle, TIOCGSERIAL, &sio ); if (ioctl_res < 0) { printf( "Failed TIOCGSERIAL ioctl: error %d (%s)\n", errno, strerror(errno) ); close( handle ); return -1; } sio.flags = ((sio.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST); sio.custom_divisor = sio.baud_base / 200000; ioctl_res = ioctl( handle, TIOCSSERIAL, &sio ); if (ioctl_res < 0) { printf( "Failed TIOCSSERIAL ioctl: error %d (%s)\n", errno, strerror(errno) ); close( handle ); return -1; } return handle; }
lio.Send is a simple function that adds an intercharacter delay of 1ms (running on Ubuntu 9.04):
int LicutIO::Send( const unsigned char *bytes, int length ) { int n; int actual_sent = 0; for (n = 0; n < length; n++) { int write_res = write( m_handle, &bytes[n], 1 ); if (write_res < 1) { printf( "%s(%p,%u) - write returned %d, errno=%d (%s)\n", __FUNCTION__, bytes, length, write_res, errno, strerror(errno) ); } else { actual_sent++; } // Add intercharacter delay after each character, including the last usleep( 1000 ); } return actual_sent; }
After reading the results of each status command, I'm forcing an additional 250ms timeout.