diff options
author | Cecil Hugh Watson <knoppmyth@gmail.com> | 2010-09-05 00:00:50 (GMT) |
---|---|---|
committer | Cecil Hugh Watson <knoppmyth@gmail.com> | 2010-09-05 00:00:50 (GMT) |
commit | 525ff794ffbaa59414fdd94c9aa4dcfc6625fa2a (patch) | |
tree | cbc9c128d61641f4e47f24d0ad6259df476e376d /abs | |
parent | cc0046aa355811c343c144e4898194c8471ec07f (diff) | |
download | linhes_pkgbuild-525ff794ffbaa59414fdd94c9aa4dcfc6625fa2a.zip linhes_pkgbuild-525ff794ffbaa59414fdd94c9aa4dcfc6625fa2a.tar.gz linhes_pkgbuild-525ff794ffbaa59414fdd94c9aa4dcfc6625fa2a.tar.bz2 |
lirc_085:lirc package w/ pvr 150 support.
Diffstat (limited to 'abs')
19 files changed, 5094 insertions, 0 deletions
diff --git a/abs/core-testing/lirc_085-utils/PKGBUILD b/abs/core-testing/lirc_085-utils/PKGBUILD new file mode 100644 index 0000000..c4d5759 --- /dev/null +++ b/abs/core-testing/lirc_085-utils/PKGBUILD @@ -0,0 +1,72 @@ +# $Id: PKGBUILD 6058 2008-07-23 02:50:00Z eric $ +# Maintainer: Paul Mattal <paul@archlinux.org> + +pkgname=lirc-utils +pkgver=0.8.5CVS +pkgrel=7 +pkgdesc="Linux Infrared Remote Control utils" +arch=(i686 x86_64) +url="http://www.lirc.org/" +license=('GPL') +_kernver=2.6.28-LinHES +depends=('alsa-lib' 'libusb' 'libx11' 'libsm' 'iguanaIR') +#makedepends=('help2man') +replaces=('lirc+pctv') +backup=('etc/lircd.conf' 'etc/lircmd.conf'\ + 'etc/conf.d/lircd') +options=('!libtool' '!makeflags') +source=(http://www.blushingpenguin.com/mark/lmilk/lirc-0.8.5-CVS-pvr150.tar.bz2 \ + lircd lircmd lirc.logrotate lircd.conf.d \ + kernel-2.6.26.patch lirc_atiusb.patch + hw_commandir.c + hw_commandir.h) +md5sums=('b96dae91b566143b3af433fa2714ec9a' '909ad968afa10e4511e1da277bb23c3b'\ + '85f7fdac55e5256967241864049bf5e9' '3deb02604b37811d41816e9b4385fcc3'\ + '5b1f8c9cd788a39a6283f93302ce5c6e' '1753acd774f50b638e6173d364de53fd'\ + '7eccd7826ab99e5cf1b9154171c8b927') + +build() { + # configure + cd $startdir/src/lirc-0.8.5-CVS-pvr150 || return 1 + cp $startdir/src/hw_commandir.* $startdir/src/lirc-0.8.5-CVS-pvr150/daemons +# patch -Np1 -i ../kernel-2.6.26.patch || return 1 + patch -Np1 -i ../lirc_atiusb.patch || return 1 + + # Disabling lirc_gpio driver as it does no longer work Kernel 2.6.22+ + sed -i -e "s:lirc_gpio\.o::" drivers/lirc_gpio/Makefile.am || return 1 + + autoreconf || return 1 + libtoolize || return 1 + + ./configure --enable-sandboxed --prefix=/usr \ + --with-driver=all --with-kerneldir=/usr/src/linux-${_kernver} \ + --with-moduledir=/lib/modules/${_kernver}/kernel/drivers/misc \ + --with-transmitter \ + || return 1 + # disable parallel and bt829 + # because of incompatibility with smp systems + sed -i -e "s:lirc_parallel::" -e "s:lirc_bt829::" \ + Makefile drivers/Makefile drivers/*/Makefile tools/Makefile \ + || return 1 + + # build + make || return 1 + make DESTDIR=$startdir/pkg install || return 1 + mkdir -p $startdir/pkg/usr/share/lirc $startdir/pkg/etc/rc.d \ + || return 1 + cp $startdir/src/{lircd,lircmd} $startdir/pkg/etc/rc.d/ \ + || return 1 + cp -rp remotes $startdir/pkg/usr/share/lirc || return 1 + chmod -R go-w $startdir/pkg/usr/share/lirc/ || return 1 + + # install the logrotate config + install -D -m644 $startdir/src/lirc.logrotate \ + $startdir/pkg/etc/logrotate.d/lirc || return 1 + + # install conf.d file + install -D -m644 $startdir/src/lircd.conf.d \ + $startdir/pkg/etc/conf.d/lircd || return 1 + + # remove built modules + rm -r $startdir/pkg/lib/ +} diff --git a/abs/core-testing/lirc_085-utils/hw_commandir.c b/abs/core-testing/lirc_085-utils/hw_commandir.c new file mode 100755 index 0000000..40ac0de --- /dev/null +++ b/abs/core-testing/lirc_085-utils/hw_commandir.c @@ -0,0 +1,1926 @@ +/* CommandIR transceivers driver 0.96 + * Supporting CommandIR II and CommandIR Mini (and multiple of both) + * April-June 2008, Matthew Bodkin + * December 2008, bug fixes, Matthew Bodkin + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <limits.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/un.h> +#include <sys/utsname.h> + +#include "hardware.h" +#include "ir_remote.h" +#include "lircd.h" +#include "receive.h" +#include "transmit.h" +#include "hw_commandir.h" +#include <usb.h> + +#define RAPID_DECODE 1 + +extern struct ir_remote *repeat_remote; +extern char *progname; + + +/********************************************************************** + * + * internal function prototypes + * + **********************************************************************/ +static int commandir_init(); +static int commandir_deinit(void); +static char *commandir_rec(struct ir_remote *remotes); +static void commandir_read_loop(); +static int cmdir_convert_RX(unsigned char *orig_rxbuffer); +static unsigned int get_time_value(unsigned int firstint, + unsigned int secondint, unsigned char overflow); +static lirc_t commandir_readdata(lirc_t timeout); +static int commandir_send(struct ir_remote *remote,struct ir_ncode *code); +static int commandir_ioctl(unsigned int cmd, void *arg); +//static void setEmitterMask(unsigned char highbyte, unsigned char lowbyte); +static void setEmitterMask(int bitmask); +static void commandir_transmit(char *buffer, int bytes, int bitmask, + unsigned int); +static void commandir_child_init(); +static void shutdown_usb(); +static void hardware_scan(); +static void hardware_disconnect(int); +static void hardware_setorder(); +static void raise_event(unsigned int); +static int commandir_read(); +static int check_irsend_commandir(unsigned char *command); +static int commandir_decode(char *command); +static int commandir_receive_decode(struct ir_remote *remote, + ir_code *prep,ir_code *codep,ir_code *postp, + int *repeat_flagp, + lirc_t *min_remaining_gapp, lirc_t *max_remaining_gapp); +static void pipeline_check(); +static int inline get_bit(int bitnum); +static void add_to_tx_pipeline(unsigned char *buffer, int bytes, + int channel_mask, unsigned int); +static void recalc_tx_available(int); +static void set_hash_mask(int channel_mask); +static int commandir2_convert_RX(unsigned short *bufferrx, + unsigned char numvalues); +static void cleanup_commandir_dev(int spotnum); + +/********************************************************************** + * + * CommandIR Vars + * + **********************************************************************/ +static int current_transmitter_mask = 0xff; +static char unsigned commandir_data_buffer[512]; +static int last_mc_time = -1; +static int commandir_rx_num = 0; + + +static char channels_en[MAX_DEVICES]; +static char open_bus_hash[USB_MAX_BUSES][USB_MAX_BUSDEV]; +static int tx_order[MAX_DEVICES]; +static char device_count = 0; +static int mini_freq[MAX_DEVICES]; +static int child_pipe_write = 0; +static char haveInited = 0; +// Fake 'commandir' remote signal values +static unsigned int signal_base[2][2] = { {100|PULSE_BIT, 200}, + {1000|PULSE_BIT, 200} }; + +// Pipes to and from the child/parent +static pid_t child_pid = -1; +static int pipe_fd[2] = { -1, -1 }; +static int pipe_tochild[2] = { -1, -1 }; +static int tochild_read = -1, tochild_write = -1; + +struct commandir_device +{ + usb_dev_handle *cmdir_udev; + int bus; + int busdev; + int interface; + int location; + int hw_type; + int hw_revision; + int hw_subversion; + unsigned char devnum; + int endpoint_max[3]; +} open_commandir_devices[4]; + +struct hardware hw_commandir = +{ + NULL, /* default device */ + -1, /* fd */ + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_SET_TRANSMITTER_MASK| + LIRC_CAN_REC_MODE2, + LIRC_MODE_PULSE, /* send_mode */ + LIRC_MODE_MODE2, /* rec_mode */ + sizeof(lirc_t), /* code_length in BITS */ + commandir_init, /* init_func */ + NULL, /* config_func */ + commandir_deinit, /* deinit_func */ + commandir_send, /* send_func */ + commandir_rec, /* rec_func */ + commandir_receive_decode, /* decode_func */ + commandir_ioctl, /* ioctl_func */ + commandir_readdata, /* readdata */ + "commandir" +}; + +/*** LIRC Interface Functions - Non-blocking parent thread +*/ + +static int commandir_receive_decode(struct ir_remote *remote, + ir_code *prep,ir_code *codep,ir_code *postp, + int *repeat_flagp, + lirc_t *min_remaining_gapp, lirc_t *max_remaining_gapp) { + + int i; + i = receive_decode(remote, + prep,codep,postp, + repeat_flagp, + min_remaining_gapp, max_remaining_gapp); + + if(i > 0){ + static char rx_char[3] = {3, 0, RXDECODE_HEADER_LIRC}; + write(tochild_write, rx_char, 3); + } + + return i; +} + + +static int commandir_init() +{ + long fd_flags; + if(haveInited){ + static char init_char[3] = {3, 0, INIT_HEADER_LIRC}; + write(tochild_write, init_char, 3); + return 1; + } + + init_rec_buffer(); // LIRC's rec + init_send_buffer(); // LIRC's send + + /* A separate process will be forked to read data from the USB + * receiver and write it to a pipe. hw.fd is set to the readable + * end of this pipe. */ + if (pipe(pipe_fd) != 0) + { + logprintf(LOG_ERR, "couldn't open pipe 1"); + return 0; + } + + hw.fd = pipe_fd[0]; // the READ end of the Pipe + + if (pipe(pipe_tochild) != 0) + { + logprintf(LOG_ERR, "couldn't open pipe 1"); + return 0; + } + + tochild_read = pipe_tochild[0]; // the READ end of the Pipe + tochild_write = pipe_tochild[1]; // the WRITE end of the Pipe + + fd_flags = fcntl(pipe_tochild[0], F_GETFL); + if(fcntl(pipe_tochild[0], F_SETFL, fd_flags | O_NONBLOCK) == -1) + { + logprintf(LOG_ERR, "can't set pipe to non-blocking"); + return 0; + } + + child_pid= fork(); + if (child_pid== -1) + { + logprintf(LOG_ERR, "couldn't fork child process"); + return 0; + } + else if (child_pid== 0) + { + child_pipe_write = pipe_fd[1]; + commandir_child_init(); + commandir_read_loop(); + return 0; + } + haveInited = 1; + + logprintf(LOG_ERR, "CommandIR driver initialized"); + return 1; +} + + +static int commandir_deinit(void) +{ + /* Trying something a bit new with this driver. Keeping the driver + * connected so in the future we can still monitor in the client */ + if(USB_KEEP_WARM && (!strncmp(progname, "lircd", 5))) + { + static char deinit_char[3] = {3, 0, DEINIT_HEADER_LIRC}; + write(tochild_write, deinit_char, 3); + logprintf(LOG_ERR, "LIRC_deinit but keeping warm"); + } + else + { + if (tochild_read >= 0) + { + if (close(tochild_read) < 0) + { + logprintf(LOG_ERR, "Error closing pipe2");; + } + tochild_read = tochild_write = -1; + } + + if(haveInited){ + // shutdown all USB + if(child_pid > 0) + { + logprintf(LOG_ERR, "Closing child process"); + kill(child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); + child_pid = -1; + haveInited = 0; + } + } + + if (hw.fd >= 0) + { + if (close(hw.fd) < 0) logprintf(LOG_ERR, "Error closing pipe"); + hw.fd = -1; + } + + logprintf(LOG_ERR, "commandir_deinit()"); + } + return(1); +} + +static int commandir_send(struct ir_remote *remote,struct ir_ncode *code) +{ + int length; + lirc_t *signals; + + if(!init_send(remote,code)) { + return 0; + } + + length = send_buffer.wptr; + signals = send_buffer.data; + + if (length <= 0 || signals == NULL) { + return 0; + } + + int cmdir_cnt =0; + char cmdir_char[70]; + + // Set the frequency of the signal along with the signal + transmitters + cmdir_char[0] = 7; + cmdir_char[1] = 0; + + cmdir_char[2] = FREQ_HEADER_LIRC; + cmdir_char[3] = (remote->freq >> 24) & (0xff); + cmdir_char[4] = (remote->freq >> 16) & (0xff); + cmdir_char[5] = (remote->freq >> 8) & (0xff); + cmdir_char[6] = (remote->freq & 0xff); + + write(tochild_write, cmdir_char, cmdir_char[0]); + + cmdir_cnt = 3; + + unsigned char * send_signals = malloc(sizeof(signals) * length + 4); + + send_signals[0] = (sizeof(lirc_t) * length + 4) & 0xff; + send_signals[1] = ((sizeof(lirc_t) * length + 4) >> 8) & 0xff; + + send_signals[2] = TX_LIRC_T; + send_signals[3] = (char)current_transmitter_mask; + + memcpy(&send_signals[4], signals, sizeof(lirc_t) * length); + + if(write(tochild_write, send_signals, + send_signals[0] + send_signals[1] * 256) < 0) + { + logprintf(LOG_ERR, "Error writing to child_write"); + } + + free(send_signals); + return(length); +} + +static char *commandir_rec(struct ir_remote *remotes) +{ + char * returnit; + if (!clear_rec_buffer()) return NULL; + returnit = decode_all(remotes); + return returnit; +} + +static int commandir_ioctl(unsigned int cmd, void *arg) +{ + unsigned int ivalue; + char cmdir_char[5]; + + switch(cmd) + { + case LIRC_SET_TRANSMITTER_MASK: + + ivalue=*(unsigned int*)arg; + + if(ivalue >= MAX_MASK) return (MAX_CHANNELS); + + /* Support the old way of setting the frequency of the signal along + * with the signal + transmitters */ + cmdir_char[0] = 5; + cmdir_char[1] = 0; + cmdir_char[2] = CHANNEL_EN_MASK; + cmdir_char[3] = (unsigned char)(ivalue & 0x00FF); // Low bits + cmdir_char[4] = (unsigned char)(ivalue >> 8); // High bits + + write(tochild_write, cmdir_char, cmdir_char[0]); + + return (0); + + default: + logprintf(LOG_ERR, "Unknown ioctl - %d", cmd); + return(-1); + } + + return 1; +} + +static lirc_t commandir_readdata(lirc_t timeout) +{ + lirc_t code = 0; + struct timeval tv = {0, timeout}; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(hw.fd, &fds); + + /* attempt a read with a timeout using select */ + if (select(hw.fd + 1, &fds, NULL, &fds, &tv) > 0) + /* if we failed to get data return 0 */ + if (read(hw.fd, &code, sizeof(lirc_t)) <= 0) + commandir_deinit(); + return code; +} + +/*** End of parent fork / LIRC accessible functions */ + + + + + + + + + + + + + + + +/*** CommandIR Client Process Functions (Handle all USB operations) + */ + +int channels_space_available[MAX_CHANNELS]; +int channels_space_updated = 0; // last updated time + +char * signalq[MAX_SIGNALQ]; // how many signals can be queued +int signalq_len[MAX_SIGNALQ]; +int signalq_bitmask[MAX_SIGNALQ]; +unsigned int signalq_frequency[MAX_SIGNALQ]; + +int top_signalq = -1; +int next_signalq_per_channel[MAX_CHANNELS]; + +unsigned char commandir_tx_start[MAX_CHANNELS*4]; +unsigned char commandir_tx_end[MAX_CHANNELS*4]; +unsigned char commandir_tx_available[MAX_CHANNELS]; +unsigned char lastSendSignalID[MAX_CHANNELS]; +unsigned char commandir_last_signal_id[MAX_CHANNELS]; + + +// Global variables to convert channel masks to consistant easier formats +unsigned char hash_mask[MAX_CHANNELS]; +unsigned char selected_channels[MAX_CHANNELS]; +unsigned char total_selected_channels = 0; +int shutdown_pending = 0; +int read_delay = WAIT_BETWEEN_READS_US; +int insert_fast_zeros = 0; + +int rx_hold = 0; + +// This is the only one for pre-pipelinging +int pre_pipeline_emitter_mask = 0x000f; // default tx on only first CommandIR + + +static void pipeline_check() +{ + /* Transmit from the pipeline if it's time and there's space + * what's available should now be updated in the main_loop + */ + + int i,j,k; + + i=0; + if(top_signalq < 0) return; + + while(i <= top_signalq) + { + + // Are ALL the channels this signal should TX on currently available? + int oktosend = 1; + set_hash_mask( signalq_bitmask[ i ] ); + for(j = 0; j<total_selected_channels; j++) + { + if(commandir_tx_available[ selected_channels[j] ] < + (36 + (signalq_len[ i ])/sizeof(lirc_t))) + { + oktosend = 0; + break; + } + } + + if(oktosend) + { + // great, TX this on all the channels. + + commandir_transmit(signalq[ i ], signalq_len[ i ], signalq_bitmask[ i ], signalq_frequency[ i ]); + + for(j = 0; j<total_selected_channels; j++) + { + /* commandir_tx_available[ selected_channels[j] ] -= + (64 + (signalq_len[ i ])/sizeof(lirc_t)); */ + commandir_tx_available[ selected_channels[j] ] = 0; + } + + /* Free up the memory, and see if there are new next_signalq's + * (any more for this channel to TX) + */ + free(signalq[i]); + + for(k=i; k<top_signalq; k++) + { + signalq[k] = signalq[k+1]; + signalq_len[k] = signalq_len[k+1]; + signalq_bitmask[k] = signalq_bitmask[k+1]; + signalq_frequency[k] = signalq_frequency[k+1]; + } + top_signalq--; + } + else + { + i++; + } + } +} + +static int get_bit(int bitnum) +{ + int r = 1; + return r << bitnum; // bit 0 is 1, bit 1 is 10, bit 2 is 100... +} + +static void add_to_tx_pipeline(unsigned char *buffer, int bytes, + int channel_mask, unsigned int frequency) +{ + /* *buffer points to a buffer that will be OVERWRITTEN; malloc our copy. + * buffer is a LIRC_T packet for CommandIR + */ + top_signalq++; + if(top_signalq > MAX_SIGNALQ) + { + logprintf(LOG_ERR, "Too many signals in queue: > %d", MAX_SIGNALQ); + return; + } + + signalq[top_signalq] = malloc(bytes); + + signalq_len[top_signalq] = bytes; + signalq_bitmask[top_signalq] = channel_mask; + signalq_frequency[top_signalq] = frequency; + + lirc_t *oldsignal, *newsignal; + int x, pulse_now = 1; + int projected_signal_length; + short aPCAFOM = 0; + float afPCAFOM = 0.0; + int difference = 0; + + afPCAFOM = (6000000.0 / ((frequency > 0) ? frequency : DEFAULT_FREQ) ) ; + aPCAFOM = afPCAFOM; + + // Trim off mid-modulation pulse fragments, add to space for exact signals + for(x=0; x<(bytes/sizeof(lirc_t)); x++) + { + oldsignal = (lirc_t *)&buffer[x*sizeof(lirc_t)]; + newsignal = (lirc_t *)signalq[top_signalq]; + newsignal += x; + + if(pulse_now==1){ + projected_signal_length = + (((int)( (*oldsignal * 12)/( afPCAFOM ) )) * aPCAFOM) / 12; + difference = *oldsignal - projected_signal_length; + // take off difference plus 1 full FOM cycle + *newsignal = *oldsignal - difference - (aPCAFOM / 12); + + } + else + { + if(difference != 0) + { + // Add anything subtracted from the pulse to the space + *newsignal = *oldsignal + difference + (aPCAFOM / 12); + difference = 0; + } + + } + + pulse_now++; + if(pulse_now > 1) pulse_now = 0; + } + + return; +} + +static void recalc_tx_available(int which_commandir) +{ + int i; + int length = 0; + static int failsafe = 0; + + if(lastSendSignalID[which_commandir] != + commandir_last_signal_id[which_commandir]) + { + /* INNOVATIONONE_FLAG:REMOVE This will be removed pending testing + * for a future release + */ + if(failsafe++ < 1000) + { + return; + } + logprintf(LOG_ERR, "Error: required the failsafe"); + } + + failsafe = 0; + for(i=which_commandir*4; i<((which_commandir+1)*4); i++) + { + length = commandir_tx_end[i] - commandir_tx_start[i]; + if(length < 0) length += 0xff; + + if(commandir_tx_available[i] < 0xff - length) + commandir_tx_available[i] = 0xff - length; + + } +} + +static void set_hash_mask(int channel_mask) // eg, 8 +{ + // bitwise set of hash_mask for easier coding... + int i,j; + j=channel_mask; + total_selected_channels = 0; + for(i=0; i<MAX_CHANNELS; i++) + { + hash_mask[i] = j & 0x01; + j = j >> 1; + if(hash_mask[i]) + selected_channels[total_selected_channels++] = i; + } +} + + +static void commandir_transmit(char *buffer, int bytes, int bitmask, + unsigned int frequency) +{ + /*** Send a TX command to 1 or more CommandIRs. + * Keep in mind: TX frequency, TX channels, TX signal length, + * which CommandIR, & what hardware version + */ + + int send_status; + unsigned char packet[TX_BUFFER_SIZE]; + /* So we know where there should be gaps between signals and more + * importantly, where there shouldn't be + */ + static char signalid = 1; + + /* Depending on the tx channels, then depending on what hardware it is, + * set the freq if needed, and send the buffer with the channel header + * that's right for that CommandIR + */ + + int devicenum = 0; + int sent = 0, tosend = 0; + unsigned char mini_tx_mask = 0; + lirc_t * signals; // have bytes/sizeof(lirc_t) signals + signals = (lirc_t *)buffer; + int total_signals = 0; + int i; + char cmdir_char[66]; + int which_signal = 0; + + total_signals = bytes / sizeof(lirc_t); + + setEmitterMask(bitmask); + + for(devicenum = 0; devicenum < device_count; devicenum++) + { + // Do we transmit on any channels on this device? + if(channels_en[ devicenum ]) + { + which_signal = 0; + switch(open_commandir_devices[ tx_order[devicenum] ].hw_type) + { + case HW_COMMANDIR_2: + + mini_tx_mask = 0; + // Short enough loop to unroll + if(channels_en[ devicenum ] & 1) mini_tx_mask |= 0x10; + if(channels_en[ devicenum ] & 2) mini_tx_mask |= 0x20; + if(channels_en[ devicenum ] & 4) mini_tx_mask |= 0x40; + if(channels_en[ devicenum ] & 8) mini_tx_mask |= 0x80; + + packet[1] = TX_COMMANDIR_II; + packet[2] = mini_tx_mask; + + short PCAFOM = 0; + float fPCAFOM = 0.0; + + if(bytes/sizeof(lirc_t) > 255) + { + logprintf(LOG_ERR, "Error: signal over max size"); + continue; + } + + fPCAFOM = (6000000 / ((frequency > 0) ? frequency : + DEFAULT_FREQ) ) ; + PCAFOM = fPCAFOM; + + lastSendSignalID[ tx_order[devicenum] ] = packet[5] = (getpid() + signalid++) + 1; + + packet[4] = PCAFOM & 0xff; + packet[3] = (PCAFOM >> 8) & 0xff; + + short packlets_to_send = 0, sending_this_time = 0; + + packlets_to_send = bytes / sizeof(lirc_t); + + int attempts; + for(attempts = 0; attempts < 10; attempts++) + { + + if((packlets_to_send*3 + 7) > open_commandir_devices[ tx_order[devicenum] ].endpoint_max[1]) + { + sending_this_time = open_commandir_devices[ tx_order[devicenum] ].endpoint_max[1]/3 - 3; + } + else + { + sending_this_time = packlets_to_send; + } + int sending; + + for(i=0; i<sending_this_time; i++) + { + sending = signals[which_signal++]; + + packet[i*3+7] = sending >> 8; // high1 + packet[i*3+8] = sending & 0xff; // low + packet[i*3+9] = sending >> 16 & 0xff; // high2 + } + + packet[0] = (sending_this_time * 3 + 7); + packet[6] = (sending_this_time == packlets_to_send) ? 0xcb : 0x00; + + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + (char*)packet, + packet[0], + USB_TIMEOUT_MS); + if(send_status < 0) + { + // Error transmitting. + hardware_scan(); + return; + } + + packlets_to_send -= ((send_status - 7) / 3); + if(!packlets_to_send) + { + // "No more packlets to send\n" + break; + } + } + continue; // for transmitting on next CommandIR device + + + case HW_COMMANDIR_MINI: + mini_tx_mask = 0; + if(channels_en[ devicenum ] & 1) mini_tx_mask |= 0x80; + if(channels_en[ devicenum ] & 2) mini_tx_mask |= 0x40; + if(channels_en[ devicenum ] & 4) mini_tx_mask |= 0x20; + if(channels_en[ devicenum ] & 8) mini_tx_mask |= 0x10; + + char freqPulseWidth = DEFAULT_PULSE_WIDTH; + + freqPulseWidth = (unsigned char)((1000000 / + ((frequency > 0) ? frequency: DEFAULT_FREQ) ) / 2); + + if(freqPulseWidth == 0) + { + freqPulseWidth = DEFAULT_PULSE_WIDTH; + } + + if(mini_freq[ tx_order[devicenum] ] != freqPulseWidth) + { + // Update the CommandIR Mini's next tx frequency + cmdir_char[0] = FREQ_HEADER; + cmdir_char[1] = freqPulseWidth; + cmdir_char[2] = 0; + mini_freq[ tx_order[devicenum] ] = freqPulseWidth; + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + cmdir_char, + 2, // 2 bytes + USB_TIMEOUT_MS); + if(send_status < 2) + { + // Error transmitting. + hardware_scan(); + return ; + } + } + + unsigned int mod_signal_length=0; + + cmdir_char[0] = TX_HEADER_NEW; + cmdir_char[1] = mini_tx_mask; + + unsigned int hibyte, lobyte; + + sent = 0; + which_signal = 0; + while(sent < (bytes / sizeof(lirc_t) * 2 ) ) + { + tosend = (bytes / sizeof(lirc_t) * 2 ) - sent; + + if(tosend > (MAX_HW_MINI_PACKET - 2)) + { + tosend = MAX_HW_MINI_PACKET - 2; + } + + for(i=0;i<(tosend/2);i++) // 2 bytes per CommandIR pkt + { + mod_signal_length = signals[which_signal++] >> 3; + hibyte = mod_signal_length/256; + lobyte = mod_signal_length%256; + cmdir_char[i*2+3] = lobyte; + cmdir_char[i*2+2] = hibyte; + } + + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + cmdir_char, + tosend + 2, + USB_TIMEOUT_MS); + if(send_status < 1) + { + // Error transmitting. + hardware_scan(); + return; + } + sent += tosend; + } // while unsent data + continue; // for transmitting on next CommandIR device + default: + logprintf(LOG_ERR, "Unknown hardware: %d", + open_commandir_devices[tx_order[devicenum]].hw_type); + } // hardware switch() + } // if we should tx on this device + } // for each device we have +} + + +static void commandir_child_init() +{ + alarm(0); + signal(SIGTERM, shutdown_usb); + signal(SIGPIPE, SIG_DFL); + signal(SIGINT, shutdown_usb); + signal(SIGHUP, SIG_IGN); + signal(SIGALRM, SIG_IGN); + + logprintf(LOG_ERR, "Child Initializing CommandIR Hardware"); + + usb_init(); + int i; + for(i=0;i<MAX_CHANNELS;i++) + { + next_signalq_per_channel[i] = -1; + channels_en[i] = 0xff; + } +/* + // Check kernel version: support fast decoding + char checkV[] = {0,0,0,0,0,0,0,0,0,0}; + FILE * checkfile; + int kernel_major = 0, kernel_minor = 0; + + checkfile=fopen("/proc/sys/kernel/osrelease", "r"); + if(checkfile!=NULL) + { + fgets(checkV, 7, checkfile); + printf("Checking: %s.\n", checkV); + printf("Version checking %s.\n", &checkV[4]); + kernel_major = atoi(&checkV[2]); + kernel_minor = atoi(&checkV[4]); + printf("Major is: %d, minor is %d.\n", kernel_major, kernel_minor); + fclose(checkfile); + } + + if(kernel_major < 6){ + insert_fast_zeros = 0; + logprintf(LOG_ERR, "Fast decoding disabled"); + } + else + { + if(kernel_minor <= 24) + { + logprintf(LOG_ERR, "Fast decoding enabled (1)"); + insert_fast_zeros = 1; + } + else + { + logprintf(LOG_ERR, "Fast decoding enabled"); + insert_fast_zeros = 2; + } + }*/ + hardware_scan(); +} + +static void hardware_disconnect(int commandir_spot) +{ + /* We had a read/write error, try disconnecting it and force _scan to + * reconnect - otherwise we may get perpetual read/write errors + */ + + int x; + + // reset the hash so we don't try and disconnect this device again + // device_count is decremented here + cleanup_commandir_dev(commandir_spot); + + raise_event(COMMANDIR_UNPLUG_1 + commandir_spot); + + /* Cases are: + removing device 0 when there's no more device (do nothing) + removing device < MAX when there's still 1+ devices (patch up) + removing device==MAX when there's more devices (do nothing) + */ + + // new device count-- from cleanup (if device_count > 0 AND commandir removed isn't 0 or max) + if( (device_count > 0) && (commandir_spot != device_count) ) + { + /* It wasn't the top device removed, and there's + * more than 1 device, so we have some vars to patch up + */ + for(x=commandir_spot; x<(device_count); x++) + { + channels_en[x] = channels_en[x+1]; + mini_freq[x] = mini_freq[x+1]; + commandir_last_signal_id[x] = commandir_last_signal_id[x+1]; + lastSendSignalID[x] = lastSendSignalID[x+1]; + memcpy(&open_commandir_devices[x], + &open_commandir_devices[x+1], + sizeof(struct commandir_device)); + } + + // Reset the TOP one that was just removed: + channels_en[(int)device_count] = 0x0f; + mini_freq[(int)device_count] = -1; + commandir_last_signal_id[(int)device_count] = 0; + lastSendSignalID[(int)device_count] = 0; + open_commandir_devices[(int)device_count].cmdir_udev = 0; + open_commandir_devices[(int)device_count].bus = 0; + open_commandir_devices[(int)device_count].busdev = 0; + open_commandir_devices[(int)device_count].interface = 0; + open_commandir_devices[(int)device_count].hw_type = 0; + open_commandir_devices[(int)device_count].hw_revision = 0; + open_commandir_devices[(int)device_count].hw_subversion = 0; + + } + + if(commandir_rx_num>=commandir_spot) + { + commandir_rx_num--; + } + + hardware_setorder(); +} + +static void hardware_setorder(){ + /* Tried to order to the detected CommandIRs based on bus and dev ids + * so they remain the same on reboot. Adding a new device in front + * will mean it becomes device 0 and emitters or scripts must be fixed + * Need a different param, these still change. + */ + + tx_order[0] = tx_order[1] = tx_order[2] = tx_order[3] = 0; + mini_freq[0] = mini_freq[1] = mini_freq[2] = mini_freq[3] = -1; + int largest = 0; + int tmpvals[4]; + int x, tx_spots, find_spot; + + for(x=0; x<device_count; x++) + { + tmpvals[x] = 256 * open_commandir_devices[x].bus + + open_commandir_devices[x].busdev; + } + + for(tx_spots = 0; tx_spots < device_count; tx_spots++) + { + largest = 0; + for(find_spot = 0; find_spot < device_count; find_spot++) + { + if(tmpvals[find_spot] > tmpvals[largest]) + { + largest = find_spot; + } + } + tx_order[device_count - tx_spots - 1 ] = largest; + tmpvals[largest] = 0; + } + + + // The formerly receiving CommandIR has been unplugged + if(commandir_rx_num < 0) + { + if(device_count > 0) + commandir_rx_num = 0; + } + + // Clear all pending signals + for(x=top_signalq; x >= 0; x--) + { + free(signalq[top_signalq]); + } + top_signalq = -1; + +} + +static void cleanup_commandir_dev(int spotnum) +{ + int location, devnum; + + location = open_commandir_devices[spotnum].location; + devnum = open_commandir_devices[spotnum].devnum; + + open_bus_hash[ location ][ devnum ] = 0; + device_count--; + + if(open_commandir_devices[spotnum].cmdir_udev==NULL) + { + return; + } + usb_release_interface(open_commandir_devices[spotnum].cmdir_udev, + open_commandir_devices[spotnum].interface); + usb_close(open_commandir_devices[spotnum].cmdir_udev); + open_commandir_devices[spotnum].cmdir_udev = NULL; +} + + +static void hardware_scan() +{ + // Scan for hardware changes; libusb doesn't notify us... + unsigned char located = 0; + struct usb_bus *bus = 0; + struct usb_device *dev = 0; + + int scan_find[MAX_DEVICES][2]; // [0]=bus#, [1]=busdev# + unsigned char found = 0; + // Using hash for performance instead of memory conservation (+1k) + unsigned char still_found[USB_MAX_BUSES][USB_MAX_BUSDEV]; + unsigned changed = 0; + int find_spot = 0; + + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == USB_CMDIR_VENDOR_ID) + { + located++; + // Do we already know about it? + if(!open_bus_hash[bus->location][dev->devnum]){ + // Then it's new, open it if we have a spot available + for(find_spot=0; find_spot < MAX_DEVICES; find_spot++) + { + if(open_commandir_devices[find_spot].cmdir_udev == NULL) + { + // Try to open here + open_commandir_devices[find_spot].cmdir_udev = usb_open(dev); + if(open_commandir_devices[find_spot].cmdir_udev == NULL) + { + logprintf(LOG_ERR, + "Error opening commandir - bus %d, device %d.", + bus, dev); + break; + } + else + { + + // Try to set configuration; not needed on Linux +// int usb_set_configuration(usb_dev_handle *dev, int configuration); + int r = 0; +// r = usb_set_configuration(open_commandir_devices[find_spot].cmdir_udev, 1); +// printf("Set_configuration returned %d.\n", r); + + r = usb_claim_interface( + open_commandir_devices[find_spot].cmdir_udev,0); + if(r < 0) + { + cleanup_commandir_dev(find_spot); + logprintf(LOG_ERR, + "Unable to claim CommandIR - Is it already busy?" + ); + logprintf(LOG_ERR, + "Try 'rmmod commandir' or check for other lircds" + ); + break; + } + else + { + // great, it's ours + open_commandir_devices[find_spot].location = bus->location; + open_commandir_devices[find_spot].devnum = dev->devnum; + open_bus_hash[bus->location][dev->devnum] = 1; + open_commandir_devices[find_spot].bus = bus->location; + open_commandir_devices[find_spot].busdev = dev->devnum; + scan_find[++found][0] = bus->location; + scan_find[found][1] = dev->devnum; + device_count++; + changed++; + still_found[bus->location][dev->devnum] = 1; + + struct usb_config_descriptor *config = &dev->config[0]; + struct usb_interface *interface = &config->interface[0]; + struct usb_interface_descriptor *ainterface = &interface->altsetting[0]; +/* struct usb_endpoint_descriptor *endpoint = &ainterface->endpoint[2];*/ + + int i;// Load wMaxPacketSize for each endpoint; subtract 0x80 + // for double-buffer bit + for (i = 0; i < ainterface->bNumEndpoints; i++) + { + open_commandir_devices[find_spot].endpoint_max[ + (ainterface->endpoint[i].bEndpointAddress >= 0x80) + ? (ainterface->endpoint[i].bEndpointAddress-0x80) + : (ainterface->endpoint[i].bEndpointAddress)] + = ainterface->endpoint[i].wMaxPacketSize; + } + + // compensate for double buffer: + open_commandir_devices[find_spot].endpoint_max[1] *= 2; + + // Always use the latest to RX: + commandir_rx_num = find_spot; + + switch(dev->descriptor.iProduct) + { + case 2: + logprintf(LOG_ERR, "Product identified as CommandIR II"); + open_commandir_devices[find_spot].hw_type = HW_COMMANDIR_2; + open_commandir_devices[find_spot].hw_revision = 0; + open_commandir_devices[find_spot].hw_subversion = 0; + + int send_status = 0, tries=20; + static char get_version[] = {2, GET_VERSION}; + + send_status = 4; // just to start the while() + + while(tries--){ + usleep(USB_TIMEOUT_US); // wait a moment + + // try moving this below: + send_status = usb_bulk_write( + open_commandir_devices[find_spot].cmdir_udev, + 2, // endpoint2 + get_version, + 2, + 1500); + if(send_status < 0) + { + logprintf(LOG_ERR, + "Unable to write version request - Is CommandIR busy? Error %d", send_status); + break; + } + + send_status = usb_bulk_read( + open_commandir_devices[find_spot].cmdir_udev, + 1, + (char *)commandir_data_buffer, + open_commandir_devices[ find_spot ].endpoint_max[1], + 1500); + + if(send_status < 0) + { + logprintf(LOG_ERR, + "Unable to read version request - Is CommandIR busy? Error %d", send_status); + cleanup_commandir_dev(find_spot); + break; + } + if(send_status==3) + { + if(commandir_data_buffer[0]==GET_VERSION) + { + // Sending back version information. + open_commandir_devices[find_spot].hw_revision = + commandir_data_buffer[1]; + open_commandir_devices[find_spot].hw_subversion = + commandir_data_buffer[2]; + logprintf(LOG_ERR, "Hardware revision is %d.%d.", + commandir_data_buffer[1], commandir_data_buffer[2]); + break; + } + else + { + continue; + } + } + + } + break; + default: + logprintf(LOG_ERR, "Product identified as CommandIR Mini"); + open_commandir_devices[find_spot].hw_type = + HW_COMMANDIR_MINI; + } + + if(open_commandir_devices[find_spot].hw_type == + HW_COMMANDIR_UNKNOWN) + { + logprintf(LOG_ERR, "Product UNKNOWN - cleanup"); + cleanup_commandir_dev(find_spot); + } + else + { + lastSendSignalID[find_spot] = 0; + commandir_last_signal_id[find_spot] = 0; + } + break; // don't keep looping through find_spot + } // claim? + }// open? + }// spot available? + }// for(spots) + } // if we haven't seen it before + else + { + still_found[bus->location][dev->devnum] = 1; + } + }// if it's a CommandIR + }// for bus dev's + }// for bus's + + if(!located) + { + logprintf(LOG_ERR, "No CommandIRs found"); + } + + /* Check if any we currently know about have been removed + * (Usually, we get a read/write error first) + */ + for(find_spot = 0; find_spot < MAX_DEVICES; find_spot++) + { + if(open_commandir_devices[find_spot].cmdir_udev != NULL) + { + if(still_found[open_commandir_devices[find_spot].location] + [open_commandir_devices[find_spot].devnum] != 1) + { + logprintf(LOG_ERR, "Commandir %d removed from [%d][%d].", find_spot,open_commandir_devices[find_spot].location, open_commandir_devices[find_spot].devnum); + raise_event(COMMANDIR_UNPLUG_1 + find_spot); + hardware_disconnect(find_spot); + commandir_rx_num = -1; + changed++; + } + } + } + + if(changed) + { + hardware_setorder(); + raise_event(COMMANDIR_REORDERED); + } + +} + + +// Shutdown everything and terminate +static void shutdown_usb() +{ + int x; + + // Wait for any TX to complete before shutting down + if(top_signalq >= 0) + { + shutdown_pending++; + logprintf(LOG_ERR, "Waiting for signals to finish transmitting before shutdown"); + return; + } + + for(x=0; x<MAX_DEVICES; x++) + { + if(open_commandir_devices[x].cmdir_udev ) + { + usb_release_interface(open_commandir_devices[x].cmdir_udev, + open_commandir_devices[x].interface); + usb_close(open_commandir_devices[x].cmdir_udev); + } + } + logprintf(LOG_ERR, "CommandIR driver child cleaned up and exiting"); + raise_event(COMMANDIR_STOPPED); + + _exit(EXIT_SUCCESS); +} + +static void commandir_read_loop() +{ + // Read from CommandIR, Write to pipe + + unsigned char commands[MAX_COMMAND]; + int curCommandStart = 0; + int curCommandLength = 0; + int bytes_read; + unsigned char periodic_checks = 0; + static unsigned char rx_decode_led[7] = {7, PROC_SET, 0x40, 0, 0,4, 2}; + static unsigned char init_led[7] = {7, PROC_SET, 0x00, 0x01, 3, 55, 2}; + static unsigned char deinit_led[7] = {7, PROC_SET, 0x0, 0x02, 3, 45, 2}; + static unsigned int LIRC_frequency = 38000; + + int send_status = 0; + int i = 0; + int tmp = 0; + int tmp2 = 0; + + raise_event(COMMANDIR_READY); + + for(;;){ + /*** This is the main loop the monitors control and TX events from + * the parent, and monitors the CommandIR RX buffer + */ + + curCommandStart = 0; + curCommandLength = 0; + bytes_read = read(tochild_read, commands, MAX_COMMAND); + + if(shutdown_pending > 0 && (top_signalq==-1)) + shutdown_usb(); + + if(bytes_read > 0){ + + while(curCommandStart < bytes_read){ + curCommandLength = commands[curCommandStart] + + commands[curCommandStart + 1] * 256; + + switch(commands[curCommandStart + 2]){ // the control value + case DEINIT_HEADER_LIRC: + for(i=0; i<device_count; i++) + { + if(open_commandir_devices[tx_order[i]].hw_type == + HW_COMMANDIR_2) + { + if(open_commandir_devices[tx_order[i]].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[tx_order[i]].cmdir_udev, + 2, // endpoint2 + (char*)deinit_led, + 7, // bytes + USB_TIMEOUT_MS); + } + rx_hold = 1; // Put a hold on RX, but queue events + } + } + + break; + case INIT_HEADER_LIRC: + for(i=0; i<device_count; i++) + { + if(open_commandir_devices[tx_order[i]].hw_type == + HW_COMMANDIR_2) + { + if(open_commandir_devices[tx_order[i] ].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[tx_order[i] ].cmdir_udev, + 2, // endpoint2 + (char*)init_led, + 7, // bytes + USB_TIMEOUT_MS); + } + rx_hold = 0; // Resume RX after queue events + } + } + break; + case RXDECODE_HEADER_LIRC: + // Successful RX decode: show it on the light. + if(open_commandir_devices[commandir_rx_num].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[commandir_rx_num].cmdir_udev, + 2, // endpoint2 + (char*)rx_decode_led, + 7, // bytes + USB_TIMEOUT_MS); + + } + break; + + case FREQ_HEADER_LIRC: + LIRC_frequency = (commands[curCommandStart + 6] & 0x000000ff) | + ((commands[curCommandStart + 5] << 8) & 0x0000ff00) | + ((commands[curCommandStart + 4] << 16) & 0x00ff0000) | + ((commands[curCommandStart + 3] << 24) & 0xff000000); + if(!LIRC_frequency) + LIRC_frequency = DEFAULT_FREQ; + break; + case TX_HEADER_NEW: + case TX_LIRC_T: + if(curCommandLength==64) + { + if(check_irsend_commandir(&commands[curCommandStart + 4])) + { + break; // it's a command for us + } + } + add_to_tx_pipeline(&commands[curCommandStart + 4], + curCommandLength - 4, pre_pipeline_emitter_mask, LIRC_frequency); + break; + + case CHANNEL_EN_MASK: + pre_pipeline_emitter_mask = (commands[curCommandStart+4] << 8) | + commands[curCommandStart+3]; + break; + } + curCommandStart += curCommandLength; + + } + } + // If we're receiving, make sure the commandir buffer doesn't overrun + if(commandir_read() < 20 ) + tmp = 2; + while(tmp-- > 0) + { + tmp2 = commandir_read(); +// printf("commandir_read() (%d) returning %d.\n", tmp,tmp2); + } + if(tmp2 < 20 ){ + // once in a while, but never while we're retreaving a signal + if(++periodic_checks>100) + { + hardware_scan(); + periodic_checks = 0; + } + else + { + usleep(read_delay); + } + } + } + +} + +static int check_irsend_commandir(unsigned char *command) +{ + // decode the code like LIRC would do, and take an action + int commandir_code = 0; + + commandir_code = commandir_decode((char*)command); + + if(commandir_code > 0xef) + { + // It's a settransmitters command + int channel = commandir_code & 0x0f; + + // can only set 1 bit from here so far.., + pre_pipeline_emitter_mask = 0x0001 << channel; + + return commandir_code; + } + + switch(commandir_code) + { + case 0x53: + read_delay /= 2; // "faster" means less time + if(read_delay < MIN_WAIT_BETWEEN_READS_US) + read_delay = MIN_WAIT_BETWEEN_READS_US; + break; + case 0x54: + read_delay *= 2; // "slower" means more time + if(read_delay > MAX_WAIT_BETWEEN_READS_US) + read_delay = MAX_WAIT_BETWEEN_READS_US; + break; + + case 0x09: + case 0x0A: + logprintf(LOG_ERR, "Re-selecting RX not implemented yet"); + break; + + case 0xe6: // disable-fast-decode + logprintf(LOG_ERR, "Fast decoding disabled"); + insert_fast_zeros = 0; + break; + + case 0xe7: // enable-fast-decode + case 0xe9: // force-fast-decode-2 + logprintf(LOG_ERR, "Fast decoding enabled"); + insert_fast_zeros = 2; + break; + + case 0xe8: // force-fast-decode-1 + logprintf(LOG_ERR, "Fast decoding enabled (1)"); + insert_fast_zeros = 1; + break; + + default: + if(commandir_code > 0x60 && commandir_code < 0xf0) + { + int ledhigh = 0, ledlow = 0, ledprog = -1; + // LED Command + switch(commandir_code >> 4) + { + case 0x6: ledlow = 0x80; break; + case 0x7: ledlow = 0x40; break; + case 0x8: ledlow = 0x20; break; + case 0x9: ledlow = 0x10; break; + case 0xa: ledlow = 0x04; break; + case 0xb: ledhigh = 0x80; break; + case 0xc: ledlow = 0x01; break; + case 0xd: ledlow = 0x02; break; + case 0xe: ledlow = 0x08; break; + } + ledprog = (commandir_code & 0x0f) - 1; + + if( ((ledhigh + ledlow) > 0) && ledprog > -1) + { + // Set light: + static unsigned char lightchange[7] = {7, + PROC_SET, 0, 0, 0, 0, 3}; + lightchange[2] = ledhigh; + lightchange[3] = ledlow; + lightchange[4] = ledprog; + int send_status = 0; + + send_status=usb_bulk_write( + open_commandir_devices[tx_order[0]].cmdir_udev, + 2, // endpoint2 + (char *)lightchange, + 7, // bytes + USB_TIMEOUT_MS); + } + + return commandir_code; // done + } + + } + + return commandir_code; +} + + +// return how many RX's were in the last receive; so we know whether to poll more frequently or not +static int commandir_read() +{ + + /*** Which CommandIRs do we have to read from? Poll RX CommandIRs + * regularly, but non-receiving CommandIRs should be more periodically + */ + + int i,j; + int read_received = 0; + int read_retval = 0; + int conv_retval = 0; + int max_read = 5; + static int zeroterminated = 0; + + for(i=0; i<device_count; i++) + { + + switch(open_commandir_devices[tx_order[i]].hw_type) + { + case HW_COMMANDIR_2: + + read_retval = usb_bulk_read( + open_commandir_devices[ tx_order[i] ].cmdir_udev, + 1, + (char *)commandir_data_buffer, + open_commandir_devices[ tx_order[i] ].endpoint_max[1], + 5000); + + if(read_retval==0) + break; + + if(read_retval < 1) + { + if(read_retval < 0) + { + if(read_retval == -19){ + logprintf(LOG_ERR, "Read Error - CommandIR probably unplugged"); + } + else + { + logprintf(LOG_ERR, + "Didn't receive a full packet from a CommandIR II! - err %d ." + , read_retval); + } + hardware_disconnect(tx_order[i]); + hardware_scan(); + } + // 0 bytes is the most frequency case; nothing to report + + break; + } + + if(commandir_data_buffer[0]==RX_HEADER_TXAVAIL) + { + // sending us the current tx_start, tx_end arrays, and where it's at + commandir_tx_start[tx_order[i]*4] = commandir_data_buffer[4]; + commandir_tx_start[tx_order[i]*4+1] = commandir_data_buffer[3]; + commandir_tx_start[tx_order[i]*4+2] = commandir_data_buffer[2]; + commandir_tx_start[tx_order[i]*4+3] = commandir_data_buffer[1]; + + commandir_tx_end[tx_order[i]*4] = commandir_data_buffer[8]; + commandir_tx_end[tx_order[i]*4+1] = commandir_data_buffer[7]; + commandir_tx_end[tx_order[i]*4+2] = commandir_data_buffer[6]; + commandir_tx_end[tx_order[i]*4+3] = commandir_data_buffer[5]; + + commandir_last_signal_id[ tx_order[i] ] = commandir_data_buffer[9]; + + recalc_tx_available(tx_order[i]); + pipeline_check(); + if(top_signalq > 0) + { + read_received++; + } + + // This ALSO implies there's NO MORE RX DATA. + lirc_t lirc_zero_buffer[2] = {0, 0}; + + int tmp4 = 0; + if(zeroterminated>1001) + { + // Send LIRC a 0,0 packet to allow IMMEDIATE decoding + if(insert_fast_zeros > 0) + { + tmp4 = write(child_pipe_write, lirc_zero_buffer, sizeof(lirc_t)*insert_fast_zeros); + } + zeroterminated = 0; + } + else + { + if((zeroterminated < 1000) && (zeroterminated > 0)) + zeroterminated += 1000; + if(zeroterminated > 1000) + zeroterminated++; + } + + break; + } + + + if(commandir_data_buffer[0]==RX_HEADER_EVENTS) + { + for(j=1; j<(read_retval); j++) + { + raise_event(commandir_data_buffer[j]+tx_order[i]*0x10); + } + } + else + { + if( (commandir_data_buffer[0]==RX_HEADER_DATA) && + (commandir_rx_num==tx_order[i]) ) + { + if(rx_hold==0) // Only if we should be listening for remote cmds + { + zeroterminated = 1; + conv_retval = commandir2_convert_RX( + (unsigned short *)&commandir_data_buffer[2], + commandir_data_buffer[1]); + read_received = conv_retval; // header + } + } + } + break; + + case HW_COMMANDIR_MINI: + + max_read = 5; + while(max_read--){ + + read_retval = usb_bulk_read( + open_commandir_devices[ tx_order[i] ].cmdir_udev, + 1, + (char *)commandir_data_buffer, + 64, + USB_TIMEOUT_MS); + + if (!(read_retval == MAX_HW_MINI_PACKET)) + { + if(read_retval == -19){ + logprintf(LOG_ERR, "Read Error - CommandIR probably unplugged"); + } + else + { + logprintf(LOG_ERR, + "Didn't receive a full packet from a Mini! - err %d ." + , read_retval); + } + + hardware_disconnect(tx_order[i]); + hardware_scan(); + break; + } + + + if ( (commandir_data_buffer[1] > 0) && + (commandir_rx_num==tx_order[i]) ) + { + conv_retval = cmdir_convert_RX(commandir_data_buffer); + + read_received += commandir_data_buffer[1]; + + if(commandir_data_buffer[1] < 20) + { + // Lots of hardware buffer room left; don't tie up CPU + break; + } + } + else + { + break; + } + } // while; should only repeat if there's more RX data + + /* CommandIR Mini only has 1 buffer */ + commandir_tx_start[tx_order[i]*4] = 0; + commandir_tx_start[tx_order[i]*4+1] = 0; + commandir_tx_start[tx_order[i]*4+2] = 0; + commandir_tx_start[tx_order[i]*4+3] = 0; + + commandir_tx_end[tx_order[i]*4] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+1] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+2] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+3] = commandir_data_buffer[2]; + + /* .. and it can't pipeline... */ + commandir_last_signal_id[i] = lastSendSignalID[i]; + recalc_tx_available(tx_order[i]); + pipeline_check(); + break; + case HW_COMMANDIR_UNKNOWN: + break; + } // end switch + } // for each attached hardware device + return read_received; +} + +static void setEmitterMask(int bitmask) +{ + channels_en[0] = bitmask & 0x0F; + channels_en[1] = (bitmask >> 4) & 0xfF; + channels_en[2] = (bitmask >> 8) & 0xfF; + channels_en[3] = (bitmask >> 12) & 0xfF; +} + + +static int commandir2_convert_RX(unsigned short *bufferrx, + unsigned char numvalues) +{ + // convert hardware timestamp values to elapsed time values + + int i; + int curpos = 0; + int bytes_w = 0; + lirc_t lirc_data_buffer[256]; + + i=0; + int pca_count = 0; + int overflows = 0; + + while(curpos < numvalues ) + { + pca_count = (bufferrx[curpos] & 0x3fff) << 2; + pca_count = pca_count / 12; + + if(bufferrx[curpos] & COMMANDIR_2_OVERFLOW_MASK) + { + overflows = bufferrx[curpos+1]; + lirc_data_buffer[i] = pca_count + (overflows * 0xffff / 12); + + if(bufferrx[curpos] & COMMANDIR_2_PULSE_MASK) + { + lirc_data_buffer[i] |= PULSE_BIT; + } + curpos++; + + } + else + { + lirc_data_buffer[i] = pca_count; + if(bufferrx[curpos] & COMMANDIR_2_PULSE_MASK) + { + lirc_data_buffer[i] |= PULSE_BIT; + } + } + + curpos++; + i++; + if(i> 255) + { + break; + } + } + + bytes_w = write(child_pipe_write, lirc_data_buffer, sizeof(lirc_t)*i); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + return 0; + } + + return bytes_w; +} + + + + +// Originally from lirc_cmdir.c +static int cmdir_convert_RX(unsigned char *orig_rxbuffer) +{ + unsigned int num_data_values = 0; + unsigned int num_data_bytes = 0; + unsigned int asint1 = 0, asint2 = 0, overflows = 0; + int i; + int bytes_w; // Pipe write + lirc_t lirc_data_buffer[256]; + + + num_data_bytes = orig_rxbuffer[1]; + + /* check if num_bytes is multiple of 3; if not, error */ + if (num_data_bytes%3 > 0) return -1; + if (num_data_bytes > 60) return -3; + if (num_data_bytes < 3) return -2; + + num_data_values = num_data_bytes/3; + + asint2 = orig_rxbuffer[3] + orig_rxbuffer[4] * 0xff; + if(last_mc_time==-1) + { + // The first time we run there's no previous time value + last_mc_time = asint2 - 110000; + if(last_mc_time < 0) last_mc_time+=0xffff; + } + + asint1 = last_mc_time; + overflows = orig_rxbuffer[5]; + + for(i=2; i<num_data_values+2; i++) + { + if(overflows < 0xff) + { + // space + lirc_data_buffer[i-2] = get_time_value(asint1, + asint2, overflows) - 26; + } + else + { // pulse + lirc_data_buffer[i-2] = get_time_value(asint1, + asint2, 0) + 26; + lirc_data_buffer[i-2] |= PULSE_BIT; + } + asint1 = asint2; + asint2 = orig_rxbuffer[i*3] + orig_rxbuffer[i*3+1] * 0xff; + overflows = orig_rxbuffer[i*3+2]; + } + last_mc_time = asint1; + + + bytes_w = write(child_pipe_write, lirc_data_buffer, sizeof(lirc_t)*num_data_values); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + goto done; + } + +done: + return bytes_w; + +} + + + + +static unsigned int get_time_value(unsigned int firstint, + unsigned int secondint, unsigned char overflow) +{ + /* get difference between two MCU timestamps, CommandIR Mini version */ + unsigned int t_answer = 0; + + if (secondint > firstint) + { + t_answer = secondint - firstint + overflow*0xffff; + } + else + { + if (overflow > 0) + { + t_answer = (65536 - firstint) + secondint + (overflow - 1)*0xffff - 250; + } + else + { + t_answer = (65536 - firstint) + secondint; + } + } + + /* clamp to long signal */ + if (t_answer > 16000000) t_answer = PULSE_MASK; + return t_answer; +} + + +static void raise_event(unsigned int eventid) +{ + /* Raise an LIRC Event by + * Generating lirc_t Pattern + */ + static lirc_t event_data[18] = {LIRCCODE_GAP, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + int i, bytes_w; + + // logprintf(LOG_ERR, "Raising event %d", eventid); + for(i=0; i<8; i++) + { + if( (eventid & 0x80) ) + { + event_data[i*2+1] = signal_base[0][0]; + event_data[i*2+2] = signal_base[0][1]; + } + else + { + event_data[i*2+1] = signal_base[1][0]; + event_data[i*2+2] = signal_base[1][1]; + } + eventid = eventid << 1; + } + + event_data[16] = LIRCCODE_GAP*4; + + bytes_w = write(child_pipe_write, event_data, sizeof(lirc_t) * 17); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + } + +} + +static int commandir_decode(char *command) +{ + // Decode the signal to a number, just like LIRC; + // there's probably a built-in way to do this. + int i; + int code = 0; + + lirc_t *codes; + codes = (lirc_t *)command; + + for(i=0; i<15; i+=2) + { + code = code << 1; + if(codes[i]==100) + code |= 1; + } + return code; +} + diff --git a/abs/core-testing/lirc_085-utils/hw_commandir.h b/abs/core-testing/lirc_085-utils/hw_commandir.h new file mode 100755 index 0000000..2280f6c --- /dev/null +++ b/abs/core-testing/lirc_085-utils/hw_commandir.h @@ -0,0 +1,175 @@ + +/**************************************************************************** + ** hw_commandir.h ********************************************************** + **************************************************************************** + * + * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de> + * -- Original hw_default.h + * Modified for CommandIR Transceivers, April-June 2008, Matthew Bodkin + * + */ + +#ifndef HW_COMMANDIR_H +#define HW_COMMANDIR_H + +#define RX_BUFFER_SIZE 1024 +#define TX_BUFFER_SIZE 1024 +#define TX_QUEUE 1 +#define RX_QUEUE 0 +#define MAX_COMMANDIRS 4 +#define MAX_COMMAND 8192 + +/* transmitter channel control */ +#define MAX_DEVICES 4 +#define MAX_CHANNELS 16 +#define DEVICE_CHANNELS 4 +#define MAX_MASK 0xffff +#define MAX_SIGNALQ 100 + +/* CommandIR control codes */ +#define CHANNEL_EN_MASK 1 +#define FREQ_HEADER 2 +#define MCU_CTRL_SIZE 3 +#define TX_HEADER 7 +#define TX_HEADER_NEW 8 +/* New for CommandIR II */ + +#define READ_INPUTS 10 +#define PROC_SET 11 +#define INIT_FUNCTION 12 +#define RX_SELECT 13 +#define TX_COMMANDIR_II 14 +/* Internal to driver */ +#define TX_LIRC_T 15 +#define FREQ_HEADER_LIRC 16 +#define RXDECODE_HEADER_LIRC 17 +#define INIT_HEADER_LIRC 18 +#define DEINIT_HEADER_LIRC 19 +#define GET_VERSION 20 + +#define COMMANDIR_2_PULSE_MASK 0x8000 +#define COMMANDIR_2_OVERFLOW_MASK 0x4000 + +#define DEFAULT_PULSE_WIDTH 13 + +#define USB_CMDIR_VENDOR_ID 0x10c4 +#define USB_CMDIR_PRODUCT_ID 0x0003 +#define USB_CMDIR_MINOR_BASE 192 + +#define HW_COMMANDIR_MINI 1 +#define HW_COMMANDIR_2 2 +#define HW_COMMANDIR_UNKNOWN 127 + +#define MAX_HW_MINI_PACKET 64 + +// CommandIR has lots of buffer room, we don't need to poll constantly +#define USB_TIMEOUT_MS 5000 +#define USB_TIMEOUT_US 1000 +#define WAIT_BETWEEN_READS_US 10000 +#define MAX_WAIT_BETWEEN_READS_US 5000000 +#define MIN_WAIT_BETWEEN_READS_US 5000 + +#define USB_MAX_BUSES 8 +#define USB_MAX_BUSDEV 127 + +#define RX_HEADER_DATA 0x01 +#define RX_HEADER_EVENTS 0x02 +#define RX_HEADER_TXAVAIL 0x03 + + +// We keep CommandIR's OPEN even on -deinit for speed and to monitor +// Other non-LIRC events (plugin, suspend, etc) +#define USB_KEEP_WARM 1 + +// CommandIR lircd.conf event driven code definitions +#define LIRCCODE_GAP 125000 +#define JACK_PLUG_1 0x01 +#define JACK_PLUG_2 0x02 +#define JACK_PLUG_3 0x03 +#define JACK_PLUG_4 0x04 +#define JACK_PLUG_5 0x11 +#define JACK_PLUG_6 0x12 +#define JACK_PLUG_7 0x13 +#define JACK_PLUG_8 0x14 +#define JACK_PLUG_9 0x21 +#define JACK_PLUG_10 0x22 +#define JACK_PLUG_11 0x23 +#define JACK_PLUG_12 0x24 +#define JACK_PLUG_13 0x31 +#define JACK_PLUG_14 0x32 +#define JACK_PLUG_15 0x33 +#define JACK_PLUG_16 0x34 + +#define JACK_UNPLUG_1 0x05 +#define JACK_UNPLUG_2 0x06 +#define JACK_UNPLUG_3 0x07 +#define JACK_UNPLUG_4 0x08 +#define JACK_UNPLUG_5 0x15 +#define JACK_UNPLUG_6 0x16 +#define JACK_UNPLUG_7 0x17 +#define JACK_UNPLUG_8 0x18 +#define JACK_UNPLUG_9 0x25 +#define JACK_UNPLUG_10 0x26 +#define JACK_UNPLUG_11 0x27 +#define JACK_UNPLUG_12 0x28 +#define JACK_UNPLUG_13 0x35 +#define JACK_UNPLUG_14 0x36 +#define JACK_UNPLUG_15 0x37 +#define JACK_UNPLUG_16 0x38 + +#define SELECT_TX_INTERNAL 0x09 +#define SELECT_TX_ExTERNAL 0x0A + +#define SELECT_TX_ON_1 0x0D +#define SELECT_TX_ON_2 0x1D +#define SELECT_TX_ON_3 0x2D +#define SELECT_TX_ON_4 0x3D + +#define JACK_PLUG_RX_1 0x0B +#define JACK_UNPLUG_RX_1 0x0C +#define JACK_PLUG_RX_2 0x1B +#define JACK_UNPLUG_RX_2 0x1C +#define JACK_PLUG_RX_3 0x2B +#define JACK_UNPLUG_RX_3 0x2C +#define JACK_PLUG_RX_4 0x3B +#define JACK_UNPLUG_RX_4 0x3C + +#define COMMANDIR_PLUG_1 0x41 +#define COMMANDIR_PLUG_2 0x42 +#define COMMANDIR_PLUG_3 0x43 +#define COMMANDIR_PLUG_4 0x44 + +#define COMMANDIR_UNPLUG_1 0x45 +#define COMMANDIR_UNPLUG_2 0x46 +#define COMMANDIR_UNPLUG_3 0x47 +#define COMMANDIR_UNPLUG_4 0x48 + +#define COMMANDIR_REORDERED 0x50 +#define COMMANDIR_READY 0x51 +#define COMMANDIR_STOPPED 0x52 +#define COMMANDIR_POLL_FASTER 0x53 +#define COMMANDIR_POLL_SLOWER 0x54 + +#define SETTRANSMITTERS_1 0xf0 +#define SETTRANSMITTERS_2 0xf1 +#define SETTRANSMITTERS_3 0xf2 +#define SETTRANSMITTERS_4 0xf3 +#define SETTRANSMITTERS_5 0xf4 +#define SETTRANSMITTERS_6 0xf5 +#define SETTRANSMITTERS_7 0xf6 +#define SETTRANSMITTERS_8 0xf7 +#define SETTRANSMITTERS_9 0xf8 +#define SETTRANSMITTERS_10 0xf9 +#define SETTRANSMITTERS_11 0xfa +#define SETTRANSMITTERS_12 0xfb +#define SETTRANSMITTERS_13 0xfc +#define SETTRANSMITTERS_14 0xfd +#define SETTRANSMITTERS_15 0xfe +#define SETTRANSMITTERS_16 0xff + +// What's in a returning data packet +#define COMMANDIR_RX_EVENTS 0x02 +#define COMMANDIR_RX_DATA 0x01 + + +#endif diff --git a/abs/core-testing/lirc_085-utils/kernel-2.6.26.patch b/abs/core-testing/lirc_085-utils/kernel-2.6.26.patch new file mode 100644 index 0000000..74bb986 --- /dev/null +++ b/abs/core-testing/lirc_085-utils/kernel-2.6.26.patch @@ -0,0 +1,122 @@ +--- a/drivers/kcompat.h 2008-01-13 11:26:28.000000000 +0100 ++++ b/drivers/kcompat.h 2008-05-14 18:37:49.000000000 +0200 +@@ -1,4 +1,4 @@ +-/* $Id: kcompat.h,v 5.34 2008/01/13 10:26:28 lirc Exp $ */ ++/* $Id: kcompat.h,v 5.36 2008/05/14 16:37:49 lirc Exp $ */ + + #ifndef _KCOMPAT_H + #define _KCOMPAT_H +@@ -36,10 +36,10 @@ + class_simple_destroy(cls); + } + +-#define lirc_class_device_create(cs, parent, dev, device, fmt, args...) \ +- class_simple_device_add(cs, dev, device, fmt, ## args) ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_simple_device_add(cs, dev, parent, fmt, ## args) + +-static inline void class_device_destroy(lirc_class_t *cls, dev_t devt) ++static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt) + { + class_simple_device_remove(devt); + } +@@ -48,20 +48,40 @@ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + +-#define lirc_class_device_create(cs, parent, dev, device, fmt, args...) \ +- class_device_create(cs, dev, device, fmt, ## args) ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_device_create(cs, dev, parent, fmt, ## args) + + #else /* >= 2.6.15 */ + +-#define lirc_class_device_create class_device_create ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) ++ ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_device_create(cs, NULL, dev, parent, fmt, ## args) ++ ++#else /* >= 2.6.26 */ ++ ++#define lirc_device_create device_create ++ ++#endif /* >= 2.6.26 */ ++ + #define LIRC_DEVFS_PREFIX + +-#endif ++#endif /* >= 2.6.15 */ + + typedef struct class lirc_class_t; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) ++ ++#define lirc_device_destroy class_device_destroy ++ ++#else ++ ++#define lirc_device_destroy device_destroy ++ + #endif + ++#endif /* >= 2.6.13 */ ++ + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) + #define LIRC_HAVE_DEVFS + #define LIRC_HAVE_DEVFS_24 +@@ -133,8 +153,8 @@ + #ifndef LIRC_HAVE_SYSFS + #define class_destroy(x) do { } while (0) + #define class_create(x, y) NULL +-#define class_device_destroy(x, y) do { } while (0) +-#define lirc_class_device_create(x, y, z, xx, yy, zz) 0 ++#define lirc_class_destroy(x, y) do { } while (0) ++#define lirc_class_create(x, y, z, xx, yy, zz) 0 + #define IS_ERR(x) 0 + typedef struct class_simple + { +--- a/drivers/lirc_dev/lirc_dev.c 2008-01-13 11:45:02.000000000 +0100 ++++ b/drivers/lirc_dev/lirc_dev.c 2008-05-14 18:37:49.000000000 +0200 +@@ -17,7 +17,7 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +- * $Id: lirc_dev.c,v 1.56 2008/01/13 10:45:02 lirc Exp $ ++ * $Id: lirc_dev.c,v 1.58 2008/05/14 16:37:49 lirc Exp $ + * + */ + +@@ -145,7 +145,8 @@ + #ifdef LIRC_HAVE_DEVFS_26 + devfs_remove(DEV_LIRC "/%u", ir->p.minor); + #endif +- class_device_destroy(lirc_class, MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); ++ lirc_device_destroy(lirc_class, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); + + if (ir->buf != ir->p.rbuf) { + lirc_buffer_free(ir->buf); +@@ -400,9 +401,9 @@ + S_IFCHR|S_IRUSR|S_IWUSR, + DEV_LIRC "/%u", ir->p.minor); + #endif +- (void) lirc_class_device_create(lirc_class, NULL, +- MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), +- ir->p.dev, "lirc%u", ir->p.minor); ++ (void) lirc_device_create(lirc_class, ir->p.dev, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), ++ "lirc%u", ir->p.minor); + + if (p->sample_rate || p->get_queue) { + /* try to fire up polling thread */ +@@ -441,7 +442,8 @@ + return minor; + + out_sysfs: +- class_device_destroy(lirc_class, MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); ++ lirc_device_destroy(lirc_class, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); + #ifdef LIRC_HAVE_DEVFS_24 + devfs_unregister(ir->devfs_handle); + #endif diff --git a/abs/core-testing/lirc_085-utils/lirc.logrotate b/abs/core-testing/lirc_085-utils/lirc.logrotate new file mode 100644 index 0000000..df97c60 --- /dev/null +++ b/abs/core-testing/lirc_085-utils/lirc.logrotate @@ -0,0 +1,8 @@ +/var/log/lircd { + missingok + notifempty + delaycompress + postrotate + /usr/bin/killall -HUP -q lircd + endscript +} diff --git a/abs/core-testing/lirc_085-utils/lirc_atiusb.patch b/abs/core-testing/lirc_085-utils/lirc_atiusb.patch new file mode 100644 index 0000000..2f0c61e --- /dev/null +++ b/abs/core-testing/lirc_085-utils/lirc_atiusb.patch @@ -0,0 +1,27 @@ +diff -ruaN lirc-0.8.4.orig/drivers/lirc_atiusb/lirc_atiusb.c lirc-0.8.4/drivers/lirc_atiusb/lirc_atiusb.c +--- lirc-0.8.4.orig/drivers/lirc_atiusb/lirc_atiusb.c 2008-05-19 08:10:35.000000000 +0000 ++++ lirc-0.8.4/drivers/lirc_atiusb/lirc_atiusb.c 2009-02-14 22:35:44.000000000 +0000 +@@ -192,8 +192,9 @@ + /* init strings */ + #define USB_OUTLEN 7 + +-static char init1[] = {0x01, 0x00, 0x20, 0x14}; +-static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; ++static char init1[] = {0x80, 0x05, 0x1b, 0x15, 0x14, 0x20, 0x24, 0x15}; ++static char init2[] = {0x83, 0x03}; ++static char init3[] = {0x84, 0xd7, 0x020}; + + struct in_endpt { + /* inner link in list of endpoints for the remote specified by ir */ +@@ -1183,8 +1184,9 @@ + oep->buf, USB_OUTLEN, usb_remote_send, + oep, oep->ep->bInterval); + +- send_packet(oep, 0x8004, init1); +- send_packet(oep, 0x8007, init2); ++ send_packet(oep, 0x8007, init1); ++ send_packet(oep, 0x8002, init2); ++ send_packet(oep, 0x8003, init3); + } + } + diff --git a/abs/core-testing/lirc_085-utils/lircd b/abs/core-testing/lirc_085-utils/lircd new file mode 100755 index 0000000..f4686d7 --- /dev/null +++ b/abs/core-testing/lirc_085-utils/lircd @@ -0,0 +1,43 @@ +#!/bin/bash + +. /etc/rc.conf +. /etc/rc.d/functions +. /etc/conf.d/lircd + +PID=$(pidof -o %PPID /usr/sbin/lircd) +case "$1" in + start) + stat_busy "Starting LIRC Daemon" + [ -n "$LIRC_DRIVER" ] && LIRC_EXTRAOPTS="-H $LIRC_DRIVER $LIRC_EXTRAOPTS" + [ -z "$PID" ] && + if [ -n "$LIRC_DEVICE" ] ; then + /usr/sbin/lircd -d "$LIRC_DEVICE" $LIRC_EXTRAOPTS $LIRC_CONFIGFILE + else + /usr/sbin/lircd $LIRC_EXTRAOPTS $LIRC_CONFIGFILE + fi + if [ $? -gt 0 ]; then + stat_fail + else + add_daemon lircd + stat_done + fi + ;; + stop) + stat_busy "Stopping LIRC Daemon" + [ ! -z "$PID" ] && kill $PID &> /dev/null + if [ $? -gt 0 ]; then + stat_fail + else + rm_daemon lircd + stat_done + fi + ;; + restart) + $0 stop + sleep 1 + $0 start + ;; + *) + echo "usage: $0 {start|stop|restart}" +esac +exit 0 diff --git a/abs/core-testing/lirc_085-utils/lircd.conf.d b/abs/core-testing/lirc_085-utils/lircd.conf.d new file mode 100644 index 0000000..760dab0 --- /dev/null +++ b/abs/core-testing/lirc_085-utils/lircd.conf.d @@ -0,0 +1,8 @@ +# +# Parameters for lirc daemon +# + +LIRC_DEVICE="/dev/lirc0" +LIRC_DRIVER="" +LIRC_EXTRAOPTS="" +LIRC_CONFIGFILE="" diff --git a/abs/core-testing/lirc_085-utils/lircmd b/abs/core-testing/lirc_085-utils/lircmd new file mode 100755 index 0000000..220c47c --- /dev/null +++ b/abs/core-testing/lirc_085-utils/lircmd @@ -0,0 +1,36 @@ +#!/bin/bash + +. /etc/rc.conf +. /etc/rc.d/functions + +PID=`pidof -o %PPID /usr/sbin/lircmd` +case "$1" in + start) + stat_busy "Starting lircmd Daemon" + [ -z "$PID" ] && /usr/sbin/lircmd + if [ $? -gt 0 ]; then + stat_fail + else + add_daemon lircmd + stat_done + fi + ;; + stop) + stat_busy "Stopping lircmd Daemon" + [ ! -z "$PID" ] && kill $PID &> /dev/null + if [ $? -gt 0 ]; then + stat_fail + else + rm_daemon lircmd + stat_done + fi + ;; + restart) + $0 stop + sleep 1 + $0 start + ;; + *) + echo "usage: $0 {start|stop|restart}" +esac +exit 0 diff --git a/abs/core-testing/lirc_085/PKGBUILD b/abs/core-testing/lirc_085/PKGBUILD new file mode 100644 index 0000000..12dc3b4 --- /dev/null +++ b/abs/core-testing/lirc_085/PKGBUILD @@ -0,0 +1,86 @@ +# $Id: PKGBUILD 14978 2008-10-11 21:04:37Z tpowa $ +# Maintainer: Paul Mattal <paul@archlinux.org> + +pkgname=lirc +pkgver=0.8.5CVS +pkgrel=17 +_kernver=2.6.28-LinHES +pkgdesc="Linux Infrared Remote Control kernel modules for stock arch kernel" +arch=(i686 x86_64) +url="http://www.lirc.org/" +license=('GPL') +depends=('lirc-utils=0.8.5CVS' 'kernel26>=2.6.27' 'kernel26<2.6.29' 'iguanaIR') +makedepends=('python') +replaces=('lirc+pctv') +options=('!makeflags') +install=$pkgname.install +source=(http://www.blushingpenguin.com/mark/lmilk/lirc-0.8.5-CVS-pvr150.tar.bz2 \ + kernel-2.6.26.patch + kernel-2.6.27.patch + lirc_atiusb.patch + http://superb-east.dl.sourceforge.net/sourceforge/mod-mce/lirc_mod_mce-0.1.5.tar.bz2 + lirc_mod_mce.patch + hw_commandir.c + hw_commandir.h + dvicoIR.rules + lirc.fdi) + +build() { + # configure + cd $startdir/src/lirc-0.8.5-CVS-pvr150 || return 1 + cp $startdir/src/hw_commandir.* $startdir/src/lirc-0.8.5-CVS-pvr150/daemons +# patch -Np1 -i ../kernel-2.6.26.patch || return 1 +# patch -Np1 -i ../kernel-2.6.27.patch || return 1 + patch -Np1 -i ../lirc_atiusb.patch || return 1 + + ./configure --enable-sandboxed --prefix=/usr \ + --with-driver=all --with-kerneldir=/usr/src/linux-${_kernver}/ \ + --with-moduledir=/lib/modules/${_kernver}/kernel/drivers/misc \ + --with-transmitter \ + || return 1 + + # disable parallel and bt829 + # because of incompatibility with smp systems + sed -i -e "s:lirc_parallel::" -e "s:lirc_bt829::" \ + Makefile drivers/Makefile drivers/*/Makefile tools/Makefile \ + || return 1 + # disable lirc_gpio due to brokeness of kernel 2.6.23 + sed -i -e "s:lirc_gpio::" \ + Makefile drivers/Makefile drivers/*/Makefile tools/Makefile \ + || return 1 + + # build + cd drivers || return 1 + make || return 1 + make DESTDIR=$startdir/pkg install || return 1 + + # set the kernel we've built for inside the install script + sed -i -e "s/KERNEL_VERSION=.*/KERNEL_VERSION=${_kernver}/g" \ + $startdir/lirc.install || return 1 + cd $startdir/src/lirc_mod_mce + cp ../lirc-0.8.5-CVS-pvr150/drivers/lirc_dev/lirc_dev.h . + patch -p1 < ../lirc_mod_mce.patch + make KDIR=/usr/src/linux-2.6.28-LinHES/ + cp lirc_mod_mce.ko $startdir/pkg/lib/modules/2.6.28-LinHES/kernel/drivers/misc/ + mv $startdir/pkg/lib/modules/2.6.28-LinHES/kernel/drivers/misc/lirc_mceusb2.ko $startdir/pkg/lib/modules/2.6.28-LinHES/kernel/drivers/misc/lirc_mceusb2.ko.not + #remove old commandir + rm $startdir/pkg/lib/modules/$_kernver/kernel/drivers/misc/lirc_cmdir.ko + rm $startdir/pkg/lib/modules/$_kernver/kernel/drivers/misc/commandir.ko + + # Add a udev rule for the DVICO remote so that if there is more than + # one hiddev device, the system cant get confused. + install -D -m644 $srcdir/dvicoIR.rules $pkgdir/etc/udev/rules.d/dvicoIR.rules + + # Add the fdi file to prevent the Dvico dual 4 remotes from screwing up keyboard interaction. + install -D -m644 $srcdir/lirc.fdi $pkgdir/usr/share/hal/fdi/preprobe/20thirdparty/lirc.fdi +} +md5sums=('b96dae91b566143b3af433fa2714ec9a' + '1753acd774f50b638e6173d364de53fd' + '6f151eb4e81fc7776a06c9063e6ad9a5' + '7eccd7826ab99e5cf1b9154171c8b927' + '21ce358809105f005e888e3b138c59e6' + 'b5d52566a9dae8d76e24e8753f33abef' + 'f059f4030afc682c9539a03bf837c1cf' + '4e698654cc44fc6c4163814acda5a7ee' + '9a3a6dc03647ee6674a166dfb884ddd6' + '203d9cd014c4276be4c84cecd103919d') diff --git a/abs/core-testing/lirc_085/dvicoIR.rules b/abs/core-testing/lirc_085/dvicoIR.rules new file mode 100644 index 0000000..ada5466 --- /dev/null +++ b/abs/core-testing/lirc_085/dvicoIR.rules @@ -0,0 +1,15 @@ +# This rule is for the Dvico Dual Digital 4 Rev 2. It has 2 IR modules +# identified, only the first of which is connected to the receiver. +# The KERNELS=="*-1" part of this rule makes sure that the first +# device is the one that gets the symlink. +KERNEL=="event*", \ + KERNELS=="*-1", \ + ATTRS{manufacturer}=="Dvico", \ + ATTRS{idVendor}=="0fe9", \ + ATTRS{idProduct}=="db98", \ + SYMLINK="input/irremote" + +# This rule is for the older style USB DVICO remote dongles. +SUBSYSTEMS=="usb", KERNEL=="hiddev*", \ + ATTRS{product}=="DVICO USB HID Remocon V1.00", \ + SYMLINK+="usb/dvicoIR" diff --git a/abs/core-testing/lirc_085/hw_commandir.c b/abs/core-testing/lirc_085/hw_commandir.c new file mode 100755 index 0000000..40ac0de --- /dev/null +++ b/abs/core-testing/lirc_085/hw_commandir.c @@ -0,0 +1,1926 @@ +/* CommandIR transceivers driver 0.96 + * Supporting CommandIR II and CommandIR Mini (and multiple of both) + * April-June 2008, Matthew Bodkin + * December 2008, bug fixes, Matthew Bodkin + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <limits.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/un.h> +#include <sys/utsname.h> + +#include "hardware.h" +#include "ir_remote.h" +#include "lircd.h" +#include "receive.h" +#include "transmit.h" +#include "hw_commandir.h" +#include <usb.h> + +#define RAPID_DECODE 1 + +extern struct ir_remote *repeat_remote; +extern char *progname; + + +/********************************************************************** + * + * internal function prototypes + * + **********************************************************************/ +static int commandir_init(); +static int commandir_deinit(void); +static char *commandir_rec(struct ir_remote *remotes); +static void commandir_read_loop(); +static int cmdir_convert_RX(unsigned char *orig_rxbuffer); +static unsigned int get_time_value(unsigned int firstint, + unsigned int secondint, unsigned char overflow); +static lirc_t commandir_readdata(lirc_t timeout); +static int commandir_send(struct ir_remote *remote,struct ir_ncode *code); +static int commandir_ioctl(unsigned int cmd, void *arg); +//static void setEmitterMask(unsigned char highbyte, unsigned char lowbyte); +static void setEmitterMask(int bitmask); +static void commandir_transmit(char *buffer, int bytes, int bitmask, + unsigned int); +static void commandir_child_init(); +static void shutdown_usb(); +static void hardware_scan(); +static void hardware_disconnect(int); +static void hardware_setorder(); +static void raise_event(unsigned int); +static int commandir_read(); +static int check_irsend_commandir(unsigned char *command); +static int commandir_decode(char *command); +static int commandir_receive_decode(struct ir_remote *remote, + ir_code *prep,ir_code *codep,ir_code *postp, + int *repeat_flagp, + lirc_t *min_remaining_gapp, lirc_t *max_remaining_gapp); +static void pipeline_check(); +static int inline get_bit(int bitnum); +static void add_to_tx_pipeline(unsigned char *buffer, int bytes, + int channel_mask, unsigned int); +static void recalc_tx_available(int); +static void set_hash_mask(int channel_mask); +static int commandir2_convert_RX(unsigned short *bufferrx, + unsigned char numvalues); +static void cleanup_commandir_dev(int spotnum); + +/********************************************************************** + * + * CommandIR Vars + * + **********************************************************************/ +static int current_transmitter_mask = 0xff; +static char unsigned commandir_data_buffer[512]; +static int last_mc_time = -1; +static int commandir_rx_num = 0; + + +static char channels_en[MAX_DEVICES]; +static char open_bus_hash[USB_MAX_BUSES][USB_MAX_BUSDEV]; +static int tx_order[MAX_DEVICES]; +static char device_count = 0; +static int mini_freq[MAX_DEVICES]; +static int child_pipe_write = 0; +static char haveInited = 0; +// Fake 'commandir' remote signal values +static unsigned int signal_base[2][2] = { {100|PULSE_BIT, 200}, + {1000|PULSE_BIT, 200} }; + +// Pipes to and from the child/parent +static pid_t child_pid = -1; +static int pipe_fd[2] = { -1, -1 }; +static int pipe_tochild[2] = { -1, -1 }; +static int tochild_read = -1, tochild_write = -1; + +struct commandir_device +{ + usb_dev_handle *cmdir_udev; + int bus; + int busdev; + int interface; + int location; + int hw_type; + int hw_revision; + int hw_subversion; + unsigned char devnum; + int endpoint_max[3]; +} open_commandir_devices[4]; + +struct hardware hw_commandir = +{ + NULL, /* default device */ + -1, /* fd */ + LIRC_CAN_SET_SEND_CARRIER| + LIRC_CAN_SEND_PULSE| + LIRC_CAN_SET_TRANSMITTER_MASK| + LIRC_CAN_REC_MODE2, + LIRC_MODE_PULSE, /* send_mode */ + LIRC_MODE_MODE2, /* rec_mode */ + sizeof(lirc_t), /* code_length in BITS */ + commandir_init, /* init_func */ + NULL, /* config_func */ + commandir_deinit, /* deinit_func */ + commandir_send, /* send_func */ + commandir_rec, /* rec_func */ + commandir_receive_decode, /* decode_func */ + commandir_ioctl, /* ioctl_func */ + commandir_readdata, /* readdata */ + "commandir" +}; + +/*** LIRC Interface Functions - Non-blocking parent thread +*/ + +static int commandir_receive_decode(struct ir_remote *remote, + ir_code *prep,ir_code *codep,ir_code *postp, + int *repeat_flagp, + lirc_t *min_remaining_gapp, lirc_t *max_remaining_gapp) { + + int i; + i = receive_decode(remote, + prep,codep,postp, + repeat_flagp, + min_remaining_gapp, max_remaining_gapp); + + if(i > 0){ + static char rx_char[3] = {3, 0, RXDECODE_HEADER_LIRC}; + write(tochild_write, rx_char, 3); + } + + return i; +} + + +static int commandir_init() +{ + long fd_flags; + if(haveInited){ + static char init_char[3] = {3, 0, INIT_HEADER_LIRC}; + write(tochild_write, init_char, 3); + return 1; + } + + init_rec_buffer(); // LIRC's rec + init_send_buffer(); // LIRC's send + + /* A separate process will be forked to read data from the USB + * receiver and write it to a pipe. hw.fd is set to the readable + * end of this pipe. */ + if (pipe(pipe_fd) != 0) + { + logprintf(LOG_ERR, "couldn't open pipe 1"); + return 0; + } + + hw.fd = pipe_fd[0]; // the READ end of the Pipe + + if (pipe(pipe_tochild) != 0) + { + logprintf(LOG_ERR, "couldn't open pipe 1"); + return 0; + } + + tochild_read = pipe_tochild[0]; // the READ end of the Pipe + tochild_write = pipe_tochild[1]; // the WRITE end of the Pipe + + fd_flags = fcntl(pipe_tochild[0], F_GETFL); + if(fcntl(pipe_tochild[0], F_SETFL, fd_flags | O_NONBLOCK) == -1) + { + logprintf(LOG_ERR, "can't set pipe to non-blocking"); + return 0; + } + + child_pid= fork(); + if (child_pid== -1) + { + logprintf(LOG_ERR, "couldn't fork child process"); + return 0; + } + else if (child_pid== 0) + { + child_pipe_write = pipe_fd[1]; + commandir_child_init(); + commandir_read_loop(); + return 0; + } + haveInited = 1; + + logprintf(LOG_ERR, "CommandIR driver initialized"); + return 1; +} + + +static int commandir_deinit(void) +{ + /* Trying something a bit new with this driver. Keeping the driver + * connected so in the future we can still monitor in the client */ + if(USB_KEEP_WARM && (!strncmp(progname, "lircd", 5))) + { + static char deinit_char[3] = {3, 0, DEINIT_HEADER_LIRC}; + write(tochild_write, deinit_char, 3); + logprintf(LOG_ERR, "LIRC_deinit but keeping warm"); + } + else + { + if (tochild_read >= 0) + { + if (close(tochild_read) < 0) + { + logprintf(LOG_ERR, "Error closing pipe2");; + } + tochild_read = tochild_write = -1; + } + + if(haveInited){ + // shutdown all USB + if(child_pid > 0) + { + logprintf(LOG_ERR, "Closing child process"); + kill(child_pid, SIGTERM); + waitpid(child_pid, NULL, 0); + child_pid = -1; + haveInited = 0; + } + } + + if (hw.fd >= 0) + { + if (close(hw.fd) < 0) logprintf(LOG_ERR, "Error closing pipe"); + hw.fd = -1; + } + + logprintf(LOG_ERR, "commandir_deinit()"); + } + return(1); +} + +static int commandir_send(struct ir_remote *remote,struct ir_ncode *code) +{ + int length; + lirc_t *signals; + + if(!init_send(remote,code)) { + return 0; + } + + length = send_buffer.wptr; + signals = send_buffer.data; + + if (length <= 0 || signals == NULL) { + return 0; + } + + int cmdir_cnt =0; + char cmdir_char[70]; + + // Set the frequency of the signal along with the signal + transmitters + cmdir_char[0] = 7; + cmdir_char[1] = 0; + + cmdir_char[2] = FREQ_HEADER_LIRC; + cmdir_char[3] = (remote->freq >> 24) & (0xff); + cmdir_char[4] = (remote->freq >> 16) & (0xff); + cmdir_char[5] = (remote->freq >> 8) & (0xff); + cmdir_char[6] = (remote->freq & 0xff); + + write(tochild_write, cmdir_char, cmdir_char[0]); + + cmdir_cnt = 3; + + unsigned char * send_signals = malloc(sizeof(signals) * length + 4); + + send_signals[0] = (sizeof(lirc_t) * length + 4) & 0xff; + send_signals[1] = ((sizeof(lirc_t) * length + 4) >> 8) & 0xff; + + send_signals[2] = TX_LIRC_T; + send_signals[3] = (char)current_transmitter_mask; + + memcpy(&send_signals[4], signals, sizeof(lirc_t) * length); + + if(write(tochild_write, send_signals, + send_signals[0] + send_signals[1] * 256) < 0) + { + logprintf(LOG_ERR, "Error writing to child_write"); + } + + free(send_signals); + return(length); +} + +static char *commandir_rec(struct ir_remote *remotes) +{ + char * returnit; + if (!clear_rec_buffer()) return NULL; + returnit = decode_all(remotes); + return returnit; +} + +static int commandir_ioctl(unsigned int cmd, void *arg) +{ + unsigned int ivalue; + char cmdir_char[5]; + + switch(cmd) + { + case LIRC_SET_TRANSMITTER_MASK: + + ivalue=*(unsigned int*)arg; + + if(ivalue >= MAX_MASK) return (MAX_CHANNELS); + + /* Support the old way of setting the frequency of the signal along + * with the signal + transmitters */ + cmdir_char[0] = 5; + cmdir_char[1] = 0; + cmdir_char[2] = CHANNEL_EN_MASK; + cmdir_char[3] = (unsigned char)(ivalue & 0x00FF); // Low bits + cmdir_char[4] = (unsigned char)(ivalue >> 8); // High bits + + write(tochild_write, cmdir_char, cmdir_char[0]); + + return (0); + + default: + logprintf(LOG_ERR, "Unknown ioctl - %d", cmd); + return(-1); + } + + return 1; +} + +static lirc_t commandir_readdata(lirc_t timeout) +{ + lirc_t code = 0; + struct timeval tv = {0, timeout}; + fd_set fds; + + FD_ZERO(&fds); + FD_SET(hw.fd, &fds); + + /* attempt a read with a timeout using select */ + if (select(hw.fd + 1, &fds, NULL, &fds, &tv) > 0) + /* if we failed to get data return 0 */ + if (read(hw.fd, &code, sizeof(lirc_t)) <= 0) + commandir_deinit(); + return code; +} + +/*** End of parent fork / LIRC accessible functions */ + + + + + + + + + + + + + + + +/*** CommandIR Client Process Functions (Handle all USB operations) + */ + +int channels_space_available[MAX_CHANNELS]; +int channels_space_updated = 0; // last updated time + +char * signalq[MAX_SIGNALQ]; // how many signals can be queued +int signalq_len[MAX_SIGNALQ]; +int signalq_bitmask[MAX_SIGNALQ]; +unsigned int signalq_frequency[MAX_SIGNALQ]; + +int top_signalq = -1; +int next_signalq_per_channel[MAX_CHANNELS]; + +unsigned char commandir_tx_start[MAX_CHANNELS*4]; +unsigned char commandir_tx_end[MAX_CHANNELS*4]; +unsigned char commandir_tx_available[MAX_CHANNELS]; +unsigned char lastSendSignalID[MAX_CHANNELS]; +unsigned char commandir_last_signal_id[MAX_CHANNELS]; + + +// Global variables to convert channel masks to consistant easier formats +unsigned char hash_mask[MAX_CHANNELS]; +unsigned char selected_channels[MAX_CHANNELS]; +unsigned char total_selected_channels = 0; +int shutdown_pending = 0; +int read_delay = WAIT_BETWEEN_READS_US; +int insert_fast_zeros = 0; + +int rx_hold = 0; + +// This is the only one for pre-pipelinging +int pre_pipeline_emitter_mask = 0x000f; // default tx on only first CommandIR + + +static void pipeline_check() +{ + /* Transmit from the pipeline if it's time and there's space + * what's available should now be updated in the main_loop + */ + + int i,j,k; + + i=0; + if(top_signalq < 0) return; + + while(i <= top_signalq) + { + + // Are ALL the channels this signal should TX on currently available? + int oktosend = 1; + set_hash_mask( signalq_bitmask[ i ] ); + for(j = 0; j<total_selected_channels; j++) + { + if(commandir_tx_available[ selected_channels[j] ] < + (36 + (signalq_len[ i ])/sizeof(lirc_t))) + { + oktosend = 0; + break; + } + } + + if(oktosend) + { + // great, TX this on all the channels. + + commandir_transmit(signalq[ i ], signalq_len[ i ], signalq_bitmask[ i ], signalq_frequency[ i ]); + + for(j = 0; j<total_selected_channels; j++) + { + /* commandir_tx_available[ selected_channels[j] ] -= + (64 + (signalq_len[ i ])/sizeof(lirc_t)); */ + commandir_tx_available[ selected_channels[j] ] = 0; + } + + /* Free up the memory, and see if there are new next_signalq's + * (any more for this channel to TX) + */ + free(signalq[i]); + + for(k=i; k<top_signalq; k++) + { + signalq[k] = signalq[k+1]; + signalq_len[k] = signalq_len[k+1]; + signalq_bitmask[k] = signalq_bitmask[k+1]; + signalq_frequency[k] = signalq_frequency[k+1]; + } + top_signalq--; + } + else + { + i++; + } + } +} + +static int get_bit(int bitnum) +{ + int r = 1; + return r << bitnum; // bit 0 is 1, bit 1 is 10, bit 2 is 100... +} + +static void add_to_tx_pipeline(unsigned char *buffer, int bytes, + int channel_mask, unsigned int frequency) +{ + /* *buffer points to a buffer that will be OVERWRITTEN; malloc our copy. + * buffer is a LIRC_T packet for CommandIR + */ + top_signalq++; + if(top_signalq > MAX_SIGNALQ) + { + logprintf(LOG_ERR, "Too many signals in queue: > %d", MAX_SIGNALQ); + return; + } + + signalq[top_signalq] = malloc(bytes); + + signalq_len[top_signalq] = bytes; + signalq_bitmask[top_signalq] = channel_mask; + signalq_frequency[top_signalq] = frequency; + + lirc_t *oldsignal, *newsignal; + int x, pulse_now = 1; + int projected_signal_length; + short aPCAFOM = 0; + float afPCAFOM = 0.0; + int difference = 0; + + afPCAFOM = (6000000.0 / ((frequency > 0) ? frequency : DEFAULT_FREQ) ) ; + aPCAFOM = afPCAFOM; + + // Trim off mid-modulation pulse fragments, add to space for exact signals + for(x=0; x<(bytes/sizeof(lirc_t)); x++) + { + oldsignal = (lirc_t *)&buffer[x*sizeof(lirc_t)]; + newsignal = (lirc_t *)signalq[top_signalq]; + newsignal += x; + + if(pulse_now==1){ + projected_signal_length = + (((int)( (*oldsignal * 12)/( afPCAFOM ) )) * aPCAFOM) / 12; + difference = *oldsignal - projected_signal_length; + // take off difference plus 1 full FOM cycle + *newsignal = *oldsignal - difference - (aPCAFOM / 12); + + } + else + { + if(difference != 0) + { + // Add anything subtracted from the pulse to the space + *newsignal = *oldsignal + difference + (aPCAFOM / 12); + difference = 0; + } + + } + + pulse_now++; + if(pulse_now > 1) pulse_now = 0; + } + + return; +} + +static void recalc_tx_available(int which_commandir) +{ + int i; + int length = 0; + static int failsafe = 0; + + if(lastSendSignalID[which_commandir] != + commandir_last_signal_id[which_commandir]) + { + /* INNOVATIONONE_FLAG:REMOVE This will be removed pending testing + * for a future release + */ + if(failsafe++ < 1000) + { + return; + } + logprintf(LOG_ERR, "Error: required the failsafe"); + } + + failsafe = 0; + for(i=which_commandir*4; i<((which_commandir+1)*4); i++) + { + length = commandir_tx_end[i] - commandir_tx_start[i]; + if(length < 0) length += 0xff; + + if(commandir_tx_available[i] < 0xff - length) + commandir_tx_available[i] = 0xff - length; + + } +} + +static void set_hash_mask(int channel_mask) // eg, 8 +{ + // bitwise set of hash_mask for easier coding... + int i,j; + j=channel_mask; + total_selected_channels = 0; + for(i=0; i<MAX_CHANNELS; i++) + { + hash_mask[i] = j & 0x01; + j = j >> 1; + if(hash_mask[i]) + selected_channels[total_selected_channels++] = i; + } +} + + +static void commandir_transmit(char *buffer, int bytes, int bitmask, + unsigned int frequency) +{ + /*** Send a TX command to 1 or more CommandIRs. + * Keep in mind: TX frequency, TX channels, TX signal length, + * which CommandIR, & what hardware version + */ + + int send_status; + unsigned char packet[TX_BUFFER_SIZE]; + /* So we know where there should be gaps between signals and more + * importantly, where there shouldn't be + */ + static char signalid = 1; + + /* Depending on the tx channels, then depending on what hardware it is, + * set the freq if needed, and send the buffer with the channel header + * that's right for that CommandIR + */ + + int devicenum = 0; + int sent = 0, tosend = 0; + unsigned char mini_tx_mask = 0; + lirc_t * signals; // have bytes/sizeof(lirc_t) signals + signals = (lirc_t *)buffer; + int total_signals = 0; + int i; + char cmdir_char[66]; + int which_signal = 0; + + total_signals = bytes / sizeof(lirc_t); + + setEmitterMask(bitmask); + + for(devicenum = 0; devicenum < device_count; devicenum++) + { + // Do we transmit on any channels on this device? + if(channels_en[ devicenum ]) + { + which_signal = 0; + switch(open_commandir_devices[ tx_order[devicenum] ].hw_type) + { + case HW_COMMANDIR_2: + + mini_tx_mask = 0; + // Short enough loop to unroll + if(channels_en[ devicenum ] & 1) mini_tx_mask |= 0x10; + if(channels_en[ devicenum ] & 2) mini_tx_mask |= 0x20; + if(channels_en[ devicenum ] & 4) mini_tx_mask |= 0x40; + if(channels_en[ devicenum ] & 8) mini_tx_mask |= 0x80; + + packet[1] = TX_COMMANDIR_II; + packet[2] = mini_tx_mask; + + short PCAFOM = 0; + float fPCAFOM = 0.0; + + if(bytes/sizeof(lirc_t) > 255) + { + logprintf(LOG_ERR, "Error: signal over max size"); + continue; + } + + fPCAFOM = (6000000 / ((frequency > 0) ? frequency : + DEFAULT_FREQ) ) ; + PCAFOM = fPCAFOM; + + lastSendSignalID[ tx_order[devicenum] ] = packet[5] = (getpid() + signalid++) + 1; + + packet[4] = PCAFOM & 0xff; + packet[3] = (PCAFOM >> 8) & 0xff; + + short packlets_to_send = 0, sending_this_time = 0; + + packlets_to_send = bytes / sizeof(lirc_t); + + int attempts; + for(attempts = 0; attempts < 10; attempts++) + { + + if((packlets_to_send*3 + 7) > open_commandir_devices[ tx_order[devicenum] ].endpoint_max[1]) + { + sending_this_time = open_commandir_devices[ tx_order[devicenum] ].endpoint_max[1]/3 - 3; + } + else + { + sending_this_time = packlets_to_send; + } + int sending; + + for(i=0; i<sending_this_time; i++) + { + sending = signals[which_signal++]; + + packet[i*3+7] = sending >> 8; // high1 + packet[i*3+8] = sending & 0xff; // low + packet[i*3+9] = sending >> 16 & 0xff; // high2 + } + + packet[0] = (sending_this_time * 3 + 7); + packet[6] = (sending_this_time == packlets_to_send) ? 0xcb : 0x00; + + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + (char*)packet, + packet[0], + USB_TIMEOUT_MS); + if(send_status < 0) + { + // Error transmitting. + hardware_scan(); + return; + } + + packlets_to_send -= ((send_status - 7) / 3); + if(!packlets_to_send) + { + // "No more packlets to send\n" + break; + } + } + continue; // for transmitting on next CommandIR device + + + case HW_COMMANDIR_MINI: + mini_tx_mask = 0; + if(channels_en[ devicenum ] & 1) mini_tx_mask |= 0x80; + if(channels_en[ devicenum ] & 2) mini_tx_mask |= 0x40; + if(channels_en[ devicenum ] & 4) mini_tx_mask |= 0x20; + if(channels_en[ devicenum ] & 8) mini_tx_mask |= 0x10; + + char freqPulseWidth = DEFAULT_PULSE_WIDTH; + + freqPulseWidth = (unsigned char)((1000000 / + ((frequency > 0) ? frequency: DEFAULT_FREQ) ) / 2); + + if(freqPulseWidth == 0) + { + freqPulseWidth = DEFAULT_PULSE_WIDTH; + } + + if(mini_freq[ tx_order[devicenum] ] != freqPulseWidth) + { + // Update the CommandIR Mini's next tx frequency + cmdir_char[0] = FREQ_HEADER; + cmdir_char[1] = freqPulseWidth; + cmdir_char[2] = 0; + mini_freq[ tx_order[devicenum] ] = freqPulseWidth; + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + cmdir_char, + 2, // 2 bytes + USB_TIMEOUT_MS); + if(send_status < 2) + { + // Error transmitting. + hardware_scan(); + return ; + } + } + + unsigned int mod_signal_length=0; + + cmdir_char[0] = TX_HEADER_NEW; + cmdir_char[1] = mini_tx_mask; + + unsigned int hibyte, lobyte; + + sent = 0; + which_signal = 0; + while(sent < (bytes / sizeof(lirc_t) * 2 ) ) + { + tosend = (bytes / sizeof(lirc_t) * 2 ) - sent; + + if(tosend > (MAX_HW_MINI_PACKET - 2)) + { + tosend = MAX_HW_MINI_PACKET - 2; + } + + for(i=0;i<(tosend/2);i++) // 2 bytes per CommandIR pkt + { + mod_signal_length = signals[which_signal++] >> 3; + hibyte = mod_signal_length/256; + lobyte = mod_signal_length%256; + cmdir_char[i*2+3] = lobyte; + cmdir_char[i*2+2] = hibyte; + } + + send_status=usb_bulk_write( + open_commandir_devices[ tx_order[devicenum] ].cmdir_udev, + 2, // endpoint2 + cmdir_char, + tosend + 2, + USB_TIMEOUT_MS); + if(send_status < 1) + { + // Error transmitting. + hardware_scan(); + return; + } + sent += tosend; + } // while unsent data + continue; // for transmitting on next CommandIR device + default: + logprintf(LOG_ERR, "Unknown hardware: %d", + open_commandir_devices[tx_order[devicenum]].hw_type); + } // hardware switch() + } // if we should tx on this device + } // for each device we have +} + + +static void commandir_child_init() +{ + alarm(0); + signal(SIGTERM, shutdown_usb); + signal(SIGPIPE, SIG_DFL); + signal(SIGINT, shutdown_usb); + signal(SIGHUP, SIG_IGN); + signal(SIGALRM, SIG_IGN); + + logprintf(LOG_ERR, "Child Initializing CommandIR Hardware"); + + usb_init(); + int i; + for(i=0;i<MAX_CHANNELS;i++) + { + next_signalq_per_channel[i] = -1; + channels_en[i] = 0xff; + } +/* + // Check kernel version: support fast decoding + char checkV[] = {0,0,0,0,0,0,0,0,0,0}; + FILE * checkfile; + int kernel_major = 0, kernel_minor = 0; + + checkfile=fopen("/proc/sys/kernel/osrelease", "r"); + if(checkfile!=NULL) + { + fgets(checkV, 7, checkfile); + printf("Checking: %s.\n", checkV); + printf("Version checking %s.\n", &checkV[4]); + kernel_major = atoi(&checkV[2]); + kernel_minor = atoi(&checkV[4]); + printf("Major is: %d, minor is %d.\n", kernel_major, kernel_minor); + fclose(checkfile); + } + + if(kernel_major < 6){ + insert_fast_zeros = 0; + logprintf(LOG_ERR, "Fast decoding disabled"); + } + else + { + if(kernel_minor <= 24) + { + logprintf(LOG_ERR, "Fast decoding enabled (1)"); + insert_fast_zeros = 1; + } + else + { + logprintf(LOG_ERR, "Fast decoding enabled"); + insert_fast_zeros = 2; + } + }*/ + hardware_scan(); +} + +static void hardware_disconnect(int commandir_spot) +{ + /* We had a read/write error, try disconnecting it and force _scan to + * reconnect - otherwise we may get perpetual read/write errors + */ + + int x; + + // reset the hash so we don't try and disconnect this device again + // device_count is decremented here + cleanup_commandir_dev(commandir_spot); + + raise_event(COMMANDIR_UNPLUG_1 + commandir_spot); + + /* Cases are: + removing device 0 when there's no more device (do nothing) + removing device < MAX when there's still 1+ devices (patch up) + removing device==MAX when there's more devices (do nothing) + */ + + // new device count-- from cleanup (if device_count > 0 AND commandir removed isn't 0 or max) + if( (device_count > 0) && (commandir_spot != device_count) ) + { + /* It wasn't the top device removed, and there's + * more than 1 device, so we have some vars to patch up + */ + for(x=commandir_spot; x<(device_count); x++) + { + channels_en[x] = channels_en[x+1]; + mini_freq[x] = mini_freq[x+1]; + commandir_last_signal_id[x] = commandir_last_signal_id[x+1]; + lastSendSignalID[x] = lastSendSignalID[x+1]; + memcpy(&open_commandir_devices[x], + &open_commandir_devices[x+1], + sizeof(struct commandir_device)); + } + + // Reset the TOP one that was just removed: + channels_en[(int)device_count] = 0x0f; + mini_freq[(int)device_count] = -1; + commandir_last_signal_id[(int)device_count] = 0; + lastSendSignalID[(int)device_count] = 0; + open_commandir_devices[(int)device_count].cmdir_udev = 0; + open_commandir_devices[(int)device_count].bus = 0; + open_commandir_devices[(int)device_count].busdev = 0; + open_commandir_devices[(int)device_count].interface = 0; + open_commandir_devices[(int)device_count].hw_type = 0; + open_commandir_devices[(int)device_count].hw_revision = 0; + open_commandir_devices[(int)device_count].hw_subversion = 0; + + } + + if(commandir_rx_num>=commandir_spot) + { + commandir_rx_num--; + } + + hardware_setorder(); +} + +static void hardware_setorder(){ + /* Tried to order to the detected CommandIRs based on bus and dev ids + * so they remain the same on reboot. Adding a new device in front + * will mean it becomes device 0 and emitters or scripts must be fixed + * Need a different param, these still change. + */ + + tx_order[0] = tx_order[1] = tx_order[2] = tx_order[3] = 0; + mini_freq[0] = mini_freq[1] = mini_freq[2] = mini_freq[3] = -1; + int largest = 0; + int tmpvals[4]; + int x, tx_spots, find_spot; + + for(x=0; x<device_count; x++) + { + tmpvals[x] = 256 * open_commandir_devices[x].bus + + open_commandir_devices[x].busdev; + } + + for(tx_spots = 0; tx_spots < device_count; tx_spots++) + { + largest = 0; + for(find_spot = 0; find_spot < device_count; find_spot++) + { + if(tmpvals[find_spot] > tmpvals[largest]) + { + largest = find_spot; + } + } + tx_order[device_count - tx_spots - 1 ] = largest; + tmpvals[largest] = 0; + } + + + // The formerly receiving CommandIR has been unplugged + if(commandir_rx_num < 0) + { + if(device_count > 0) + commandir_rx_num = 0; + } + + // Clear all pending signals + for(x=top_signalq; x >= 0; x--) + { + free(signalq[top_signalq]); + } + top_signalq = -1; + +} + +static void cleanup_commandir_dev(int spotnum) +{ + int location, devnum; + + location = open_commandir_devices[spotnum].location; + devnum = open_commandir_devices[spotnum].devnum; + + open_bus_hash[ location ][ devnum ] = 0; + device_count--; + + if(open_commandir_devices[spotnum].cmdir_udev==NULL) + { + return; + } + usb_release_interface(open_commandir_devices[spotnum].cmdir_udev, + open_commandir_devices[spotnum].interface); + usb_close(open_commandir_devices[spotnum].cmdir_udev); + open_commandir_devices[spotnum].cmdir_udev = NULL; +} + + +static void hardware_scan() +{ + // Scan for hardware changes; libusb doesn't notify us... + unsigned char located = 0; + struct usb_bus *bus = 0; + struct usb_device *dev = 0; + + int scan_find[MAX_DEVICES][2]; // [0]=bus#, [1]=busdev# + unsigned char found = 0; + // Using hash for performance instead of memory conservation (+1k) + unsigned char still_found[USB_MAX_BUSES][USB_MAX_BUSDEV]; + unsigned changed = 0; + int find_spot = 0; + + usb_find_busses(); + usb_find_devices(); + + for (bus = usb_busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == USB_CMDIR_VENDOR_ID) + { + located++; + // Do we already know about it? + if(!open_bus_hash[bus->location][dev->devnum]){ + // Then it's new, open it if we have a spot available + for(find_spot=0; find_spot < MAX_DEVICES; find_spot++) + { + if(open_commandir_devices[find_spot].cmdir_udev == NULL) + { + // Try to open here + open_commandir_devices[find_spot].cmdir_udev = usb_open(dev); + if(open_commandir_devices[find_spot].cmdir_udev == NULL) + { + logprintf(LOG_ERR, + "Error opening commandir - bus %d, device %d.", + bus, dev); + break; + } + else + { + + // Try to set configuration; not needed on Linux +// int usb_set_configuration(usb_dev_handle *dev, int configuration); + int r = 0; +// r = usb_set_configuration(open_commandir_devices[find_spot].cmdir_udev, 1); +// printf("Set_configuration returned %d.\n", r); + + r = usb_claim_interface( + open_commandir_devices[find_spot].cmdir_udev,0); + if(r < 0) + { + cleanup_commandir_dev(find_spot); + logprintf(LOG_ERR, + "Unable to claim CommandIR - Is it already busy?" + ); + logprintf(LOG_ERR, + "Try 'rmmod commandir' or check for other lircds" + ); + break; + } + else + { + // great, it's ours + open_commandir_devices[find_spot].location = bus->location; + open_commandir_devices[find_spot].devnum = dev->devnum; + open_bus_hash[bus->location][dev->devnum] = 1; + open_commandir_devices[find_spot].bus = bus->location; + open_commandir_devices[find_spot].busdev = dev->devnum; + scan_find[++found][0] = bus->location; + scan_find[found][1] = dev->devnum; + device_count++; + changed++; + still_found[bus->location][dev->devnum] = 1; + + struct usb_config_descriptor *config = &dev->config[0]; + struct usb_interface *interface = &config->interface[0]; + struct usb_interface_descriptor *ainterface = &interface->altsetting[0]; +/* struct usb_endpoint_descriptor *endpoint = &ainterface->endpoint[2];*/ + + int i;// Load wMaxPacketSize for each endpoint; subtract 0x80 + // for double-buffer bit + for (i = 0; i < ainterface->bNumEndpoints; i++) + { + open_commandir_devices[find_spot].endpoint_max[ + (ainterface->endpoint[i].bEndpointAddress >= 0x80) + ? (ainterface->endpoint[i].bEndpointAddress-0x80) + : (ainterface->endpoint[i].bEndpointAddress)] + = ainterface->endpoint[i].wMaxPacketSize; + } + + // compensate for double buffer: + open_commandir_devices[find_spot].endpoint_max[1] *= 2; + + // Always use the latest to RX: + commandir_rx_num = find_spot; + + switch(dev->descriptor.iProduct) + { + case 2: + logprintf(LOG_ERR, "Product identified as CommandIR II"); + open_commandir_devices[find_spot].hw_type = HW_COMMANDIR_2; + open_commandir_devices[find_spot].hw_revision = 0; + open_commandir_devices[find_spot].hw_subversion = 0; + + int send_status = 0, tries=20; + static char get_version[] = {2, GET_VERSION}; + + send_status = 4; // just to start the while() + + while(tries--){ + usleep(USB_TIMEOUT_US); // wait a moment + + // try moving this below: + send_status = usb_bulk_write( + open_commandir_devices[find_spot].cmdir_udev, + 2, // endpoint2 + get_version, + 2, + 1500); + if(send_status < 0) + { + logprintf(LOG_ERR, + "Unable to write version request - Is CommandIR busy? Error %d", send_status); + break; + } + + send_status = usb_bulk_read( + open_commandir_devices[find_spot].cmdir_udev, + 1, + (char *)commandir_data_buffer, + open_commandir_devices[ find_spot ].endpoint_max[1], + 1500); + + if(send_status < 0) + { + logprintf(LOG_ERR, + "Unable to read version request - Is CommandIR busy? Error %d", send_status); + cleanup_commandir_dev(find_spot); + break; + } + if(send_status==3) + { + if(commandir_data_buffer[0]==GET_VERSION) + { + // Sending back version information. + open_commandir_devices[find_spot].hw_revision = + commandir_data_buffer[1]; + open_commandir_devices[find_spot].hw_subversion = + commandir_data_buffer[2]; + logprintf(LOG_ERR, "Hardware revision is %d.%d.", + commandir_data_buffer[1], commandir_data_buffer[2]); + break; + } + else + { + continue; + } + } + + } + break; + default: + logprintf(LOG_ERR, "Product identified as CommandIR Mini"); + open_commandir_devices[find_spot].hw_type = + HW_COMMANDIR_MINI; + } + + if(open_commandir_devices[find_spot].hw_type == + HW_COMMANDIR_UNKNOWN) + { + logprintf(LOG_ERR, "Product UNKNOWN - cleanup"); + cleanup_commandir_dev(find_spot); + } + else + { + lastSendSignalID[find_spot] = 0; + commandir_last_signal_id[find_spot] = 0; + } + break; // don't keep looping through find_spot + } // claim? + }// open? + }// spot available? + }// for(spots) + } // if we haven't seen it before + else + { + still_found[bus->location][dev->devnum] = 1; + } + }// if it's a CommandIR + }// for bus dev's + }// for bus's + + if(!located) + { + logprintf(LOG_ERR, "No CommandIRs found"); + } + + /* Check if any we currently know about have been removed + * (Usually, we get a read/write error first) + */ + for(find_spot = 0; find_spot < MAX_DEVICES; find_spot++) + { + if(open_commandir_devices[find_spot].cmdir_udev != NULL) + { + if(still_found[open_commandir_devices[find_spot].location] + [open_commandir_devices[find_spot].devnum] != 1) + { + logprintf(LOG_ERR, "Commandir %d removed from [%d][%d].", find_spot,open_commandir_devices[find_spot].location, open_commandir_devices[find_spot].devnum); + raise_event(COMMANDIR_UNPLUG_1 + find_spot); + hardware_disconnect(find_spot); + commandir_rx_num = -1; + changed++; + } + } + } + + if(changed) + { + hardware_setorder(); + raise_event(COMMANDIR_REORDERED); + } + +} + + +// Shutdown everything and terminate +static void shutdown_usb() +{ + int x; + + // Wait for any TX to complete before shutting down + if(top_signalq >= 0) + { + shutdown_pending++; + logprintf(LOG_ERR, "Waiting for signals to finish transmitting before shutdown"); + return; + } + + for(x=0; x<MAX_DEVICES; x++) + { + if(open_commandir_devices[x].cmdir_udev ) + { + usb_release_interface(open_commandir_devices[x].cmdir_udev, + open_commandir_devices[x].interface); + usb_close(open_commandir_devices[x].cmdir_udev); + } + } + logprintf(LOG_ERR, "CommandIR driver child cleaned up and exiting"); + raise_event(COMMANDIR_STOPPED); + + _exit(EXIT_SUCCESS); +} + +static void commandir_read_loop() +{ + // Read from CommandIR, Write to pipe + + unsigned char commands[MAX_COMMAND]; + int curCommandStart = 0; + int curCommandLength = 0; + int bytes_read; + unsigned char periodic_checks = 0; + static unsigned char rx_decode_led[7] = {7, PROC_SET, 0x40, 0, 0,4, 2}; + static unsigned char init_led[7] = {7, PROC_SET, 0x00, 0x01, 3, 55, 2}; + static unsigned char deinit_led[7] = {7, PROC_SET, 0x0, 0x02, 3, 45, 2}; + static unsigned int LIRC_frequency = 38000; + + int send_status = 0; + int i = 0; + int tmp = 0; + int tmp2 = 0; + + raise_event(COMMANDIR_READY); + + for(;;){ + /*** This is the main loop the monitors control and TX events from + * the parent, and monitors the CommandIR RX buffer + */ + + curCommandStart = 0; + curCommandLength = 0; + bytes_read = read(tochild_read, commands, MAX_COMMAND); + + if(shutdown_pending > 0 && (top_signalq==-1)) + shutdown_usb(); + + if(bytes_read > 0){ + + while(curCommandStart < bytes_read){ + curCommandLength = commands[curCommandStart] + + commands[curCommandStart + 1] * 256; + + switch(commands[curCommandStart + 2]){ // the control value + case DEINIT_HEADER_LIRC: + for(i=0; i<device_count; i++) + { + if(open_commandir_devices[tx_order[i]].hw_type == + HW_COMMANDIR_2) + { + if(open_commandir_devices[tx_order[i]].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[tx_order[i]].cmdir_udev, + 2, // endpoint2 + (char*)deinit_led, + 7, // bytes + USB_TIMEOUT_MS); + } + rx_hold = 1; // Put a hold on RX, but queue events + } + } + + break; + case INIT_HEADER_LIRC: + for(i=0; i<device_count; i++) + { + if(open_commandir_devices[tx_order[i]].hw_type == + HW_COMMANDIR_2) + { + if(open_commandir_devices[tx_order[i] ].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[tx_order[i] ].cmdir_udev, + 2, // endpoint2 + (char*)init_led, + 7, // bytes + USB_TIMEOUT_MS); + } + rx_hold = 0; // Resume RX after queue events + } + } + break; + case RXDECODE_HEADER_LIRC: + // Successful RX decode: show it on the light. + if(open_commandir_devices[commandir_rx_num].cmdir_udev > 0) + { + send_status=usb_bulk_write( + open_commandir_devices[commandir_rx_num].cmdir_udev, + 2, // endpoint2 + (char*)rx_decode_led, + 7, // bytes + USB_TIMEOUT_MS); + + } + break; + + case FREQ_HEADER_LIRC: + LIRC_frequency = (commands[curCommandStart + 6] & 0x000000ff) | + ((commands[curCommandStart + 5] << 8) & 0x0000ff00) | + ((commands[curCommandStart + 4] << 16) & 0x00ff0000) | + ((commands[curCommandStart + 3] << 24) & 0xff000000); + if(!LIRC_frequency) + LIRC_frequency = DEFAULT_FREQ; + break; + case TX_HEADER_NEW: + case TX_LIRC_T: + if(curCommandLength==64) + { + if(check_irsend_commandir(&commands[curCommandStart + 4])) + { + break; // it's a command for us + } + } + add_to_tx_pipeline(&commands[curCommandStart + 4], + curCommandLength - 4, pre_pipeline_emitter_mask, LIRC_frequency); + break; + + case CHANNEL_EN_MASK: + pre_pipeline_emitter_mask = (commands[curCommandStart+4] << 8) | + commands[curCommandStart+3]; + break; + } + curCommandStart += curCommandLength; + + } + } + // If we're receiving, make sure the commandir buffer doesn't overrun + if(commandir_read() < 20 ) + tmp = 2; + while(tmp-- > 0) + { + tmp2 = commandir_read(); +// printf("commandir_read() (%d) returning %d.\n", tmp,tmp2); + } + if(tmp2 < 20 ){ + // once in a while, but never while we're retreaving a signal + if(++periodic_checks>100) + { + hardware_scan(); + periodic_checks = 0; + } + else + { + usleep(read_delay); + } + } + } + +} + +static int check_irsend_commandir(unsigned char *command) +{ + // decode the code like LIRC would do, and take an action + int commandir_code = 0; + + commandir_code = commandir_decode((char*)command); + + if(commandir_code > 0xef) + { + // It's a settransmitters command + int channel = commandir_code & 0x0f; + + // can only set 1 bit from here so far.., + pre_pipeline_emitter_mask = 0x0001 << channel; + + return commandir_code; + } + + switch(commandir_code) + { + case 0x53: + read_delay /= 2; // "faster" means less time + if(read_delay < MIN_WAIT_BETWEEN_READS_US) + read_delay = MIN_WAIT_BETWEEN_READS_US; + break; + case 0x54: + read_delay *= 2; // "slower" means more time + if(read_delay > MAX_WAIT_BETWEEN_READS_US) + read_delay = MAX_WAIT_BETWEEN_READS_US; + break; + + case 0x09: + case 0x0A: + logprintf(LOG_ERR, "Re-selecting RX not implemented yet"); + break; + + case 0xe6: // disable-fast-decode + logprintf(LOG_ERR, "Fast decoding disabled"); + insert_fast_zeros = 0; + break; + + case 0xe7: // enable-fast-decode + case 0xe9: // force-fast-decode-2 + logprintf(LOG_ERR, "Fast decoding enabled"); + insert_fast_zeros = 2; + break; + + case 0xe8: // force-fast-decode-1 + logprintf(LOG_ERR, "Fast decoding enabled (1)"); + insert_fast_zeros = 1; + break; + + default: + if(commandir_code > 0x60 && commandir_code < 0xf0) + { + int ledhigh = 0, ledlow = 0, ledprog = -1; + // LED Command + switch(commandir_code >> 4) + { + case 0x6: ledlow = 0x80; break; + case 0x7: ledlow = 0x40; break; + case 0x8: ledlow = 0x20; break; + case 0x9: ledlow = 0x10; break; + case 0xa: ledlow = 0x04; break; + case 0xb: ledhigh = 0x80; break; + case 0xc: ledlow = 0x01; break; + case 0xd: ledlow = 0x02; break; + case 0xe: ledlow = 0x08; break; + } + ledprog = (commandir_code & 0x0f) - 1; + + if( ((ledhigh + ledlow) > 0) && ledprog > -1) + { + // Set light: + static unsigned char lightchange[7] = {7, + PROC_SET, 0, 0, 0, 0, 3}; + lightchange[2] = ledhigh; + lightchange[3] = ledlow; + lightchange[4] = ledprog; + int send_status = 0; + + send_status=usb_bulk_write( + open_commandir_devices[tx_order[0]].cmdir_udev, + 2, // endpoint2 + (char *)lightchange, + 7, // bytes + USB_TIMEOUT_MS); + } + + return commandir_code; // done + } + + } + + return commandir_code; +} + + +// return how many RX's were in the last receive; so we know whether to poll more frequently or not +static int commandir_read() +{ + + /*** Which CommandIRs do we have to read from? Poll RX CommandIRs + * regularly, but non-receiving CommandIRs should be more periodically + */ + + int i,j; + int read_received = 0; + int read_retval = 0; + int conv_retval = 0; + int max_read = 5; + static int zeroterminated = 0; + + for(i=0; i<device_count; i++) + { + + switch(open_commandir_devices[tx_order[i]].hw_type) + { + case HW_COMMANDIR_2: + + read_retval = usb_bulk_read( + open_commandir_devices[ tx_order[i] ].cmdir_udev, + 1, + (char *)commandir_data_buffer, + open_commandir_devices[ tx_order[i] ].endpoint_max[1], + 5000); + + if(read_retval==0) + break; + + if(read_retval < 1) + { + if(read_retval < 0) + { + if(read_retval == -19){ + logprintf(LOG_ERR, "Read Error - CommandIR probably unplugged"); + } + else + { + logprintf(LOG_ERR, + "Didn't receive a full packet from a CommandIR II! - err %d ." + , read_retval); + } + hardware_disconnect(tx_order[i]); + hardware_scan(); + } + // 0 bytes is the most frequency case; nothing to report + + break; + } + + if(commandir_data_buffer[0]==RX_HEADER_TXAVAIL) + { + // sending us the current tx_start, tx_end arrays, and where it's at + commandir_tx_start[tx_order[i]*4] = commandir_data_buffer[4]; + commandir_tx_start[tx_order[i]*4+1] = commandir_data_buffer[3]; + commandir_tx_start[tx_order[i]*4+2] = commandir_data_buffer[2]; + commandir_tx_start[tx_order[i]*4+3] = commandir_data_buffer[1]; + + commandir_tx_end[tx_order[i]*4] = commandir_data_buffer[8]; + commandir_tx_end[tx_order[i]*4+1] = commandir_data_buffer[7]; + commandir_tx_end[tx_order[i]*4+2] = commandir_data_buffer[6]; + commandir_tx_end[tx_order[i]*4+3] = commandir_data_buffer[5]; + + commandir_last_signal_id[ tx_order[i] ] = commandir_data_buffer[9]; + + recalc_tx_available(tx_order[i]); + pipeline_check(); + if(top_signalq > 0) + { + read_received++; + } + + // This ALSO implies there's NO MORE RX DATA. + lirc_t lirc_zero_buffer[2] = {0, 0}; + + int tmp4 = 0; + if(zeroterminated>1001) + { + // Send LIRC a 0,0 packet to allow IMMEDIATE decoding + if(insert_fast_zeros > 0) + { + tmp4 = write(child_pipe_write, lirc_zero_buffer, sizeof(lirc_t)*insert_fast_zeros); + } + zeroterminated = 0; + } + else + { + if((zeroterminated < 1000) && (zeroterminated > 0)) + zeroterminated += 1000; + if(zeroterminated > 1000) + zeroterminated++; + } + + break; + } + + + if(commandir_data_buffer[0]==RX_HEADER_EVENTS) + { + for(j=1; j<(read_retval); j++) + { + raise_event(commandir_data_buffer[j]+tx_order[i]*0x10); + } + } + else + { + if( (commandir_data_buffer[0]==RX_HEADER_DATA) && + (commandir_rx_num==tx_order[i]) ) + { + if(rx_hold==0) // Only if we should be listening for remote cmds + { + zeroterminated = 1; + conv_retval = commandir2_convert_RX( + (unsigned short *)&commandir_data_buffer[2], + commandir_data_buffer[1]); + read_received = conv_retval; // header + } + } + } + break; + + case HW_COMMANDIR_MINI: + + max_read = 5; + while(max_read--){ + + read_retval = usb_bulk_read( + open_commandir_devices[ tx_order[i] ].cmdir_udev, + 1, + (char *)commandir_data_buffer, + 64, + USB_TIMEOUT_MS); + + if (!(read_retval == MAX_HW_MINI_PACKET)) + { + if(read_retval == -19){ + logprintf(LOG_ERR, "Read Error - CommandIR probably unplugged"); + } + else + { + logprintf(LOG_ERR, + "Didn't receive a full packet from a Mini! - err %d ." + , read_retval); + } + + hardware_disconnect(tx_order[i]); + hardware_scan(); + break; + } + + + if ( (commandir_data_buffer[1] > 0) && + (commandir_rx_num==tx_order[i]) ) + { + conv_retval = cmdir_convert_RX(commandir_data_buffer); + + read_received += commandir_data_buffer[1]; + + if(commandir_data_buffer[1] < 20) + { + // Lots of hardware buffer room left; don't tie up CPU + break; + } + } + else + { + break; + } + } // while; should only repeat if there's more RX data + + /* CommandIR Mini only has 1 buffer */ + commandir_tx_start[tx_order[i]*4] = 0; + commandir_tx_start[tx_order[i]*4+1] = 0; + commandir_tx_start[tx_order[i]*4+2] = 0; + commandir_tx_start[tx_order[i]*4+3] = 0; + + commandir_tx_end[tx_order[i]*4] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+1] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+2] = commandir_data_buffer[2]; + commandir_tx_end[tx_order[i]*4+3] = commandir_data_buffer[2]; + + /* .. and it can't pipeline... */ + commandir_last_signal_id[i] = lastSendSignalID[i]; + recalc_tx_available(tx_order[i]); + pipeline_check(); + break; + case HW_COMMANDIR_UNKNOWN: + break; + } // end switch + } // for each attached hardware device + return read_received; +} + +static void setEmitterMask(int bitmask) +{ + channels_en[0] = bitmask & 0x0F; + channels_en[1] = (bitmask >> 4) & 0xfF; + channels_en[2] = (bitmask >> 8) & 0xfF; + channels_en[3] = (bitmask >> 12) & 0xfF; +} + + +static int commandir2_convert_RX(unsigned short *bufferrx, + unsigned char numvalues) +{ + // convert hardware timestamp values to elapsed time values + + int i; + int curpos = 0; + int bytes_w = 0; + lirc_t lirc_data_buffer[256]; + + i=0; + int pca_count = 0; + int overflows = 0; + + while(curpos < numvalues ) + { + pca_count = (bufferrx[curpos] & 0x3fff) << 2; + pca_count = pca_count / 12; + + if(bufferrx[curpos] & COMMANDIR_2_OVERFLOW_MASK) + { + overflows = bufferrx[curpos+1]; + lirc_data_buffer[i] = pca_count + (overflows * 0xffff / 12); + + if(bufferrx[curpos] & COMMANDIR_2_PULSE_MASK) + { + lirc_data_buffer[i] |= PULSE_BIT; + } + curpos++; + + } + else + { + lirc_data_buffer[i] = pca_count; + if(bufferrx[curpos] & COMMANDIR_2_PULSE_MASK) + { + lirc_data_buffer[i] |= PULSE_BIT; + } + } + + curpos++; + i++; + if(i> 255) + { + break; + } + } + + bytes_w = write(child_pipe_write, lirc_data_buffer, sizeof(lirc_t)*i); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + return 0; + } + + return bytes_w; +} + + + + +// Originally from lirc_cmdir.c +static int cmdir_convert_RX(unsigned char *orig_rxbuffer) +{ + unsigned int num_data_values = 0; + unsigned int num_data_bytes = 0; + unsigned int asint1 = 0, asint2 = 0, overflows = 0; + int i; + int bytes_w; // Pipe write + lirc_t lirc_data_buffer[256]; + + + num_data_bytes = orig_rxbuffer[1]; + + /* check if num_bytes is multiple of 3; if not, error */ + if (num_data_bytes%3 > 0) return -1; + if (num_data_bytes > 60) return -3; + if (num_data_bytes < 3) return -2; + + num_data_values = num_data_bytes/3; + + asint2 = orig_rxbuffer[3] + orig_rxbuffer[4] * 0xff; + if(last_mc_time==-1) + { + // The first time we run there's no previous time value + last_mc_time = asint2 - 110000; + if(last_mc_time < 0) last_mc_time+=0xffff; + } + + asint1 = last_mc_time; + overflows = orig_rxbuffer[5]; + + for(i=2; i<num_data_values+2; i++) + { + if(overflows < 0xff) + { + // space + lirc_data_buffer[i-2] = get_time_value(asint1, + asint2, overflows) - 26; + } + else + { // pulse + lirc_data_buffer[i-2] = get_time_value(asint1, + asint2, 0) + 26; + lirc_data_buffer[i-2] |= PULSE_BIT; + } + asint1 = asint2; + asint2 = orig_rxbuffer[i*3] + orig_rxbuffer[i*3+1] * 0xff; + overflows = orig_rxbuffer[i*3+2]; + } + last_mc_time = asint1; + + + bytes_w = write(child_pipe_write, lirc_data_buffer, sizeof(lirc_t)*num_data_values); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + goto done; + } + +done: + return bytes_w; + +} + + + + +static unsigned int get_time_value(unsigned int firstint, + unsigned int secondint, unsigned char overflow) +{ + /* get difference between two MCU timestamps, CommandIR Mini version */ + unsigned int t_answer = 0; + + if (secondint > firstint) + { + t_answer = secondint - firstint + overflow*0xffff; + } + else + { + if (overflow > 0) + { + t_answer = (65536 - firstint) + secondint + (overflow - 1)*0xffff - 250; + } + else + { + t_answer = (65536 - firstint) + secondint; + } + } + + /* clamp to long signal */ + if (t_answer > 16000000) t_answer = PULSE_MASK; + return t_answer; +} + + +static void raise_event(unsigned int eventid) +{ + /* Raise an LIRC Event by + * Generating lirc_t Pattern + */ + static lirc_t event_data[18] = {LIRCCODE_GAP, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + int i, bytes_w; + + // logprintf(LOG_ERR, "Raising event %d", eventid); + for(i=0; i<8; i++) + { + if( (eventid & 0x80) ) + { + event_data[i*2+1] = signal_base[0][0]; + event_data[i*2+2] = signal_base[0][1]; + } + else + { + event_data[i*2+1] = signal_base[1][0]; + event_data[i*2+2] = signal_base[1][1]; + } + eventid = eventid << 1; + } + + event_data[16] = LIRCCODE_GAP*4; + + bytes_w = write(child_pipe_write, event_data, sizeof(lirc_t) * 17); + + if (bytes_w < 0) + { + logprintf(LOG_ERR, "Can't write to LIRC pipe! %d", child_pipe_write); + } + +} + +static int commandir_decode(char *command) +{ + // Decode the signal to a number, just like LIRC; + // there's probably a built-in way to do this. + int i; + int code = 0; + + lirc_t *codes; + codes = (lirc_t *)command; + + for(i=0; i<15; i+=2) + { + code = code << 1; + if(codes[i]==100) + code |= 1; + } + return code; +} + diff --git a/abs/core-testing/lirc_085/hw_commandir.h b/abs/core-testing/lirc_085/hw_commandir.h new file mode 100755 index 0000000..2280f6c --- /dev/null +++ b/abs/core-testing/lirc_085/hw_commandir.h @@ -0,0 +1,175 @@ + +/**************************************************************************** + ** hw_commandir.h ********************************************************** + **************************************************************************** + * + * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de> + * -- Original hw_default.h + * Modified for CommandIR Transceivers, April-June 2008, Matthew Bodkin + * + */ + +#ifndef HW_COMMANDIR_H +#define HW_COMMANDIR_H + +#define RX_BUFFER_SIZE 1024 +#define TX_BUFFER_SIZE 1024 +#define TX_QUEUE 1 +#define RX_QUEUE 0 +#define MAX_COMMANDIRS 4 +#define MAX_COMMAND 8192 + +/* transmitter channel control */ +#define MAX_DEVICES 4 +#define MAX_CHANNELS 16 +#define DEVICE_CHANNELS 4 +#define MAX_MASK 0xffff +#define MAX_SIGNALQ 100 + +/* CommandIR control codes */ +#define CHANNEL_EN_MASK 1 +#define FREQ_HEADER 2 +#define MCU_CTRL_SIZE 3 +#define TX_HEADER 7 +#define TX_HEADER_NEW 8 +/* New for CommandIR II */ + +#define READ_INPUTS 10 +#define PROC_SET 11 +#define INIT_FUNCTION 12 +#define RX_SELECT 13 +#define TX_COMMANDIR_II 14 +/* Internal to driver */ +#define TX_LIRC_T 15 +#define FREQ_HEADER_LIRC 16 +#define RXDECODE_HEADER_LIRC 17 +#define INIT_HEADER_LIRC 18 +#define DEINIT_HEADER_LIRC 19 +#define GET_VERSION 20 + +#define COMMANDIR_2_PULSE_MASK 0x8000 +#define COMMANDIR_2_OVERFLOW_MASK 0x4000 + +#define DEFAULT_PULSE_WIDTH 13 + +#define USB_CMDIR_VENDOR_ID 0x10c4 +#define USB_CMDIR_PRODUCT_ID 0x0003 +#define USB_CMDIR_MINOR_BASE 192 + +#define HW_COMMANDIR_MINI 1 +#define HW_COMMANDIR_2 2 +#define HW_COMMANDIR_UNKNOWN 127 + +#define MAX_HW_MINI_PACKET 64 + +// CommandIR has lots of buffer room, we don't need to poll constantly +#define USB_TIMEOUT_MS 5000 +#define USB_TIMEOUT_US 1000 +#define WAIT_BETWEEN_READS_US 10000 +#define MAX_WAIT_BETWEEN_READS_US 5000000 +#define MIN_WAIT_BETWEEN_READS_US 5000 + +#define USB_MAX_BUSES 8 +#define USB_MAX_BUSDEV 127 + +#define RX_HEADER_DATA 0x01 +#define RX_HEADER_EVENTS 0x02 +#define RX_HEADER_TXAVAIL 0x03 + + +// We keep CommandIR's OPEN even on -deinit for speed and to monitor +// Other non-LIRC events (plugin, suspend, etc) +#define USB_KEEP_WARM 1 + +// CommandIR lircd.conf event driven code definitions +#define LIRCCODE_GAP 125000 +#define JACK_PLUG_1 0x01 +#define JACK_PLUG_2 0x02 +#define JACK_PLUG_3 0x03 +#define JACK_PLUG_4 0x04 +#define JACK_PLUG_5 0x11 +#define JACK_PLUG_6 0x12 +#define JACK_PLUG_7 0x13 +#define JACK_PLUG_8 0x14 +#define JACK_PLUG_9 0x21 +#define JACK_PLUG_10 0x22 +#define JACK_PLUG_11 0x23 +#define JACK_PLUG_12 0x24 +#define JACK_PLUG_13 0x31 +#define JACK_PLUG_14 0x32 +#define JACK_PLUG_15 0x33 +#define JACK_PLUG_16 0x34 + +#define JACK_UNPLUG_1 0x05 +#define JACK_UNPLUG_2 0x06 +#define JACK_UNPLUG_3 0x07 +#define JACK_UNPLUG_4 0x08 +#define JACK_UNPLUG_5 0x15 +#define JACK_UNPLUG_6 0x16 +#define JACK_UNPLUG_7 0x17 +#define JACK_UNPLUG_8 0x18 +#define JACK_UNPLUG_9 0x25 +#define JACK_UNPLUG_10 0x26 +#define JACK_UNPLUG_11 0x27 +#define JACK_UNPLUG_12 0x28 +#define JACK_UNPLUG_13 0x35 +#define JACK_UNPLUG_14 0x36 +#define JACK_UNPLUG_15 0x37 +#define JACK_UNPLUG_16 0x38 + +#define SELECT_TX_INTERNAL 0x09 +#define SELECT_TX_ExTERNAL 0x0A + +#define SELECT_TX_ON_1 0x0D +#define SELECT_TX_ON_2 0x1D +#define SELECT_TX_ON_3 0x2D +#define SELECT_TX_ON_4 0x3D + +#define JACK_PLUG_RX_1 0x0B +#define JACK_UNPLUG_RX_1 0x0C +#define JACK_PLUG_RX_2 0x1B +#define JACK_UNPLUG_RX_2 0x1C +#define JACK_PLUG_RX_3 0x2B +#define JACK_UNPLUG_RX_3 0x2C +#define JACK_PLUG_RX_4 0x3B +#define JACK_UNPLUG_RX_4 0x3C + +#define COMMANDIR_PLUG_1 0x41 +#define COMMANDIR_PLUG_2 0x42 +#define COMMANDIR_PLUG_3 0x43 +#define COMMANDIR_PLUG_4 0x44 + +#define COMMANDIR_UNPLUG_1 0x45 +#define COMMANDIR_UNPLUG_2 0x46 +#define COMMANDIR_UNPLUG_3 0x47 +#define COMMANDIR_UNPLUG_4 0x48 + +#define COMMANDIR_REORDERED 0x50 +#define COMMANDIR_READY 0x51 +#define COMMANDIR_STOPPED 0x52 +#define COMMANDIR_POLL_FASTER 0x53 +#define COMMANDIR_POLL_SLOWER 0x54 + +#define SETTRANSMITTERS_1 0xf0 +#define SETTRANSMITTERS_2 0xf1 +#define SETTRANSMITTERS_3 0xf2 +#define SETTRANSMITTERS_4 0xf3 +#define SETTRANSMITTERS_5 0xf4 +#define SETTRANSMITTERS_6 0xf5 +#define SETTRANSMITTERS_7 0xf6 +#define SETTRANSMITTERS_8 0xf7 +#define SETTRANSMITTERS_9 0xf8 +#define SETTRANSMITTERS_10 0xf9 +#define SETTRANSMITTERS_11 0xfa +#define SETTRANSMITTERS_12 0xfb +#define SETTRANSMITTERS_13 0xfc +#define SETTRANSMITTERS_14 0xfd +#define SETTRANSMITTERS_15 0xfe +#define SETTRANSMITTERS_16 0xff + +// What's in a returning data packet +#define COMMANDIR_RX_EVENTS 0x02 +#define COMMANDIR_RX_DATA 0x01 + + +#endif diff --git a/abs/core-testing/lirc_085/kernel-2.6.26.patch b/abs/core-testing/lirc_085/kernel-2.6.26.patch new file mode 100644 index 0000000..74bb986 --- /dev/null +++ b/abs/core-testing/lirc_085/kernel-2.6.26.patch @@ -0,0 +1,122 @@ +--- a/drivers/kcompat.h 2008-01-13 11:26:28.000000000 +0100 ++++ b/drivers/kcompat.h 2008-05-14 18:37:49.000000000 +0200 +@@ -1,4 +1,4 @@ +-/* $Id: kcompat.h,v 5.34 2008/01/13 10:26:28 lirc Exp $ */ ++/* $Id: kcompat.h,v 5.36 2008/05/14 16:37:49 lirc Exp $ */ + + #ifndef _KCOMPAT_H + #define _KCOMPAT_H +@@ -36,10 +36,10 @@ + class_simple_destroy(cls); + } + +-#define lirc_class_device_create(cs, parent, dev, device, fmt, args...) \ +- class_simple_device_add(cs, dev, device, fmt, ## args) ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_simple_device_add(cs, dev, parent, fmt, ## args) + +-static inline void class_device_destroy(lirc_class_t *cls, dev_t devt) ++static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt) + { + class_simple_device_remove(devt); + } +@@ -48,20 +48,40 @@ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + +-#define lirc_class_device_create(cs, parent, dev, device, fmt, args...) \ +- class_device_create(cs, dev, device, fmt, ## args) ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_device_create(cs, dev, parent, fmt, ## args) + + #else /* >= 2.6.15 */ + +-#define lirc_class_device_create class_device_create ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) ++ ++#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++ class_device_create(cs, NULL, dev, parent, fmt, ## args) ++ ++#else /* >= 2.6.26 */ ++ ++#define lirc_device_create device_create ++ ++#endif /* >= 2.6.26 */ ++ + #define LIRC_DEVFS_PREFIX + +-#endif ++#endif /* >= 2.6.15 */ + + typedef struct class lirc_class_t; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) ++ ++#define lirc_device_destroy class_device_destroy ++ ++#else ++ ++#define lirc_device_destroy device_destroy ++ + #endif + ++#endif /* >= 2.6.13 */ ++ + #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) + #define LIRC_HAVE_DEVFS + #define LIRC_HAVE_DEVFS_24 +@@ -133,8 +153,8 @@ + #ifndef LIRC_HAVE_SYSFS + #define class_destroy(x) do { } while (0) + #define class_create(x, y) NULL +-#define class_device_destroy(x, y) do { } while (0) +-#define lirc_class_device_create(x, y, z, xx, yy, zz) 0 ++#define lirc_class_destroy(x, y) do { } while (0) ++#define lirc_class_create(x, y, z, xx, yy, zz) 0 + #define IS_ERR(x) 0 + typedef struct class_simple + { +--- a/drivers/lirc_dev/lirc_dev.c 2008-01-13 11:45:02.000000000 +0100 ++++ b/drivers/lirc_dev/lirc_dev.c 2008-05-14 18:37:49.000000000 +0200 +@@ -17,7 +17,7 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +- * $Id: lirc_dev.c,v 1.56 2008/01/13 10:45:02 lirc Exp $ ++ * $Id: lirc_dev.c,v 1.58 2008/05/14 16:37:49 lirc Exp $ + * + */ + +@@ -145,7 +145,8 @@ + #ifdef LIRC_HAVE_DEVFS_26 + devfs_remove(DEV_LIRC "/%u", ir->p.minor); + #endif +- class_device_destroy(lirc_class, MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); ++ lirc_device_destroy(lirc_class, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); + + if (ir->buf != ir->p.rbuf) { + lirc_buffer_free(ir->buf); +@@ -400,9 +401,9 @@ + S_IFCHR|S_IRUSR|S_IWUSR, + DEV_LIRC "/%u", ir->p.minor); + #endif +- (void) lirc_class_device_create(lirc_class, NULL, +- MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), +- ir->p.dev, "lirc%u", ir->p.minor); ++ (void) lirc_device_create(lirc_class, ir->p.dev, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), ++ "lirc%u", ir->p.minor); + + if (p->sample_rate || p->get_queue) { + /* try to fire up polling thread */ +@@ -441,7 +442,8 @@ + return minor; + + out_sysfs: +- class_device_destroy(lirc_class, MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); ++ lirc_device_destroy(lirc_class, ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor)); + #ifdef LIRC_HAVE_DEVFS_24 + devfs_unregister(ir->devfs_handle); + #endif diff --git a/abs/core-testing/lirc_085/kernel-2.6.27.patch b/abs/core-testing/lirc_085/kernel-2.6.27.patch new file mode 100644 index 0000000..05cf75b --- /dev/null +++ b/abs/core-testing/lirc_085/kernel-2.6.27.patch @@ -0,0 +1,78 @@ +diff -Nur lirc-0.8.3.orig/drivers/lirc_dev/lirc_dev.c lirc-0.8.3/drivers/lirc_dev/lirc_dev.c +--- lirc-0.8.3.orig/drivers/lirc_dev/lirc_dev.c 2008-01-13 11:45:02.000000000 +0100 ++++ lirc-0.8.3/drivers/lirc_dev/lirc_dev.c 2008-10-10 16:29:15.000000000 +0200 +@@ -49,7 +49,7 @@ + #include <linux/uaccess.h> + #include <linux/errno.h> + #endif +-#include <asm/semaphore.h> ++#include <linux/semaphore.h> + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + #include <linux/wrapper.h> + #endif +diff -Nur lirc-0.8.3.orig/drivers/lirc_i2c/lirc_i2c.c lirc-0.8.3/drivers/lirc_i2c/lirc_i2c.c +--- lirc-0.8.3.orig/drivers/lirc_i2c/lirc_i2c.c 2008-05-04 15:49:53.000000000 +0200 ++++ lirc-0.8.3/drivers/lirc_i2c/lirc_i2c.c 2008-10-10 16:29:00.000000000 +0200 +@@ -54,7 +54,7 @@ + #include <linux/i2c.h> + #include <linux/i2c-algo-bit.h> + +-#include <asm/semaphore.h> ++#include <linux/semaphore.h> + + #include "drivers/kcompat.h" + #include "drivers/lirc_dev/lirc_dev.h" +--- lirc-0.8.3.orig/drivers/kcompat.h 2008/05/14 16:37:49 5.36 ++++ lirc-0.8.3.orig/drivers/kcompat.h 2008/09/27 08:16:15 5.37 +@@ -36,7 +36,7 @@ + class_simple_destroy(cls); + } + +-#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ + class_simple_device_add(cs, dev, parent, fmt, ## args) + + static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt) +@@ -48,20 +48,29 @@ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) + +-#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ + class_device_create(cs, dev, parent, fmt, ## args) + + #else /* >= 2.6.15 */ + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) + +-#define lirc_device_create(cs, parent, dev, fmt, args...) \ ++#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ + class_device_create(cs, NULL, dev, parent, fmt, ## args) + + #else /* >= 2.6.26 */ + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) ++ ++#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ ++ class_device_create(cs, parent, dev, fmt, ## args) ++ ++#else /* >= 2.6.27 */ ++ + #define lirc_device_create device_create + ++#endif /* >= 2.6.27 */ ++ + #endif /* >= 2.6.26 */ + + #define LIRC_DEVFS_PREFIX +--- lirc-0.8.3.orig/drivers/lirc_dev/lirc_dev.c 2008/09/06 07:30:16 1.60 ++++ lirc-0.8.3.orig/drivers/lirc_dev/lirc_dev.c 2008/09/27 08:16:15 1.61 +@@ -397,7 +397,7 @@ + DEV_LIRC "/%u", ir->p.minor); + #endif + (void) lirc_device_create(lirc_class, ir->p.dev, +- MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), ++ MKDEV(IRCTL_DEV_MAJOR, ir->p.minor), NULL, + "lirc%u", ir->p.minor); + + if (p->sample_rate || p->get_queue) { diff --git a/abs/core-testing/lirc_085/lirc.fdi b/abs/core-testing/lirc_085/lirc.fdi new file mode 100644 index 0000000..6f2443a --- /dev/null +++ b/abs/core-testing/lirc_085/lirc.fdi @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<deviceinfo version="0.2"> + <device> + <!-- This rule prevents the Dvico dual digital4 rev 2 + remote input device from making your keyboard act wierd. --> + <match key="info.product" contains_ncase="IR-receiver inside an USB DVB receiver"> + <merge key="info.ignore" type="bool">true</merge> + </match> + </device> +</deviceinfo> diff --git a/abs/core-testing/lirc_085/lirc.install b/abs/core-testing/lirc_085/lirc.install new file mode 100644 index 0000000..53340e5 --- /dev/null +++ b/abs/core-testing/lirc_085/lirc.install @@ -0,0 +1,50 @@ +# This is a default template for a post-install scriptlet. You can +# remove any functions you don't need (and this header). + +# arg 1: the new package version +pre_install() { + /bin/true +} + +# arg 1: the new package version +post_install() { + # updating module dependencies + echo ">>> Updating module dependencies. Please wait ..." + KERNEL_VERSION=2.6.28-LinHES + depmod -v $KERNEL_VERSION > /dev/null 2>&1 + /bin/true +} + +# arg 1: the new package version +# arg 2: the old package version +pre_upgrade() { + /bin/true +} + +# arg 1: the new package version +# arg 2: the old package version +post_upgrade() { + # updating module dependencies + echo ">>> Updating module dependencies. Please wait ..." + KERNEL_VERSION=2.6.28-LinHES + depmod -v $KERNEL_VERSION > /dev/null 2>&1 + /bin/true +} + +# arg 1: the old package version +pre_remove() { + /bin/true +} + +# arg 1: the old package version +post_remove() { + # updating module dependencies + echo ">>> Updating module dependencies. Please wait ..." + KERNEL_VERSION=2.6.28-LinHES + depmod -v $KERNEL_VERSION > /dev/null 2>&1 + /bin/true +} + +op=$1 +shift +$op $* diff --git a/abs/core-testing/lirc_085/lirc_atiusb.patch b/abs/core-testing/lirc_085/lirc_atiusb.patch new file mode 100644 index 0000000..2f0c61e --- /dev/null +++ b/abs/core-testing/lirc_085/lirc_atiusb.patch @@ -0,0 +1,27 @@ +diff -ruaN lirc-0.8.4.orig/drivers/lirc_atiusb/lirc_atiusb.c lirc-0.8.4/drivers/lirc_atiusb/lirc_atiusb.c +--- lirc-0.8.4.orig/drivers/lirc_atiusb/lirc_atiusb.c 2008-05-19 08:10:35.000000000 +0000 ++++ lirc-0.8.4/drivers/lirc_atiusb/lirc_atiusb.c 2009-02-14 22:35:44.000000000 +0000 +@@ -192,8 +192,9 @@ + /* init strings */ + #define USB_OUTLEN 7 + +-static char init1[] = {0x01, 0x00, 0x20, 0x14}; +-static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; ++static char init1[] = {0x80, 0x05, 0x1b, 0x15, 0x14, 0x20, 0x24, 0x15}; ++static char init2[] = {0x83, 0x03}; ++static char init3[] = {0x84, 0xd7, 0x020}; + + struct in_endpt { + /* inner link in list of endpoints for the remote specified by ir */ +@@ -1183,8 +1184,9 @@ + oep->buf, USB_OUTLEN, usb_remote_send, + oep, oep->ep->bInterval); + +- send_packet(oep, 0x8004, init1); +- send_packet(oep, 0x8007, init2); ++ send_packet(oep, 0x8007, init1); ++ send_packet(oep, 0x8002, init2); ++ send_packet(oep, 0x8003, init3); + } + } + diff --git a/abs/core-testing/lirc_085/lirc_mod_mce.patch b/abs/core-testing/lirc_085/lirc_mod_mce.patch new file mode 100644 index 0000000..1dc6644 --- /dev/null +++ b/abs/core-testing/lirc_085/lirc_mod_mce.patch @@ -0,0 +1,187 @@ +diff -Naru lirc_mod_mce/lirc_mod_mce.c lirc_mod_mce_new/lirc_mod_mce.c +--- lirc_mod_mce/lirc_mod_mce.c 2008-04-18 02:12:28.000000000 +0930 ++++ lirc_mod_mce_new/lirc_mod_mce.c 2009-11-22 18:45:24.000000000 +1030 +@@ -171,17 +171,76 @@ + #define VENDOR_TATUNG 0x1460 + #define VENDOR_GATEWAY 0x107b + #define VENDOR_SHUTTLE 0x1308 ++#define VENDOR_PHILIPS 0x0471 ++#define VENDOR_SMK 0x0609 ++#define VENDOR_TATUNG 0x1460 ++#define VENDOR_GATEWAY 0x107b ++#define VENDOR_SHUTTLE 0x1308 ++#define VENDOR_SHUTTLE2 0x051c ++#define VENDOR_MITSUMI 0x03ee ++#define VENDOR_TOPSEED 0x1784 ++#define VENDOR_RICAVISION 0x179d ++#define VENDOR_ITRON 0x195d ++#define VENDOR_FIC 0x1509 ++#define VENDOR_LG 0x043e ++#define VENDOR_MICROSOFT 0x045e ++#define VENDOR_FORMOSA 0x147a ++#define VENDOR_FINTEK 0x1934 + #define VENDOR_PINNACLE 0x2304 + +- + static struct usb_device_id usb_remote_table [] = { +- { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, /* Philips eHome Infrared Transciever */ +- { USB_DEVICE(VENDOR_SMK, 0x031d) }, /* SMK/Toshiba G83C0004D410 */ +- { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, /* Tatung eHome Infrared Transceiver */ +- { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, /* Shuttle eHome Infrared Transceiver */ +- { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, /* Gateway eHome Infrared Transceiver */ +- { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, /* Pinnacle Remote USB RC6 */ +- { } /* Terminating entry */ ++ /* Philips eHome Infrared Transciever */ ++ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, ++ /* Philips Infrared Transciever - HP branded */ ++ { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, ++ /* Philips SRM5100 */ ++ { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, ++ /* SMK/Toshiba G83C0004D410 */ ++ { USB_DEVICE(VENDOR_SMK, 0x031d) }, ++ /* SMK eHome Infrared Transceiver (Sony VAIO) */ ++ { USB_DEVICE(VENDOR_SMK, 0x0322) }, ++ /* bundled with Hauppauge PVR-150 */ ++ { USB_DEVICE(VENDOR_SMK, 0x0334) }, ++ /* Tatung eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, ++ /* Shuttle eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, ++ /* Shuttle eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, ++ /* Gateway eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, ++ /* Mitsumi */ ++ { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, ++ /* Topseed eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, ++ /* Topseed HP eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, ++ /* Topseed eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, ++ /* Topseed eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, ++ /* Ricavision internal Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, ++ /* Itron ione Libra Q-11 */ ++ { USB_DEVICE(VENDOR_ITRON, 0x7002) }, ++ /* FIC eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_FIC, 0x9242) }, ++ /* LG eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_LG, 0x9803) }, ++ /* Microsoft MCE Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, ++ /* Formosa eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, ++ /* Formosa aim / Trust MCE Infrared Receiver */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, ++ /* Formosa Industrial Computing / Beanbag Emulation Device */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, ++ /* Fintek eHome Infrared Transceiver */ ++ { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, ++ /* Pinnacle Remote USB RC6 */ ++ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, ++ /* Terminating entry */ ++ { } + }; + + static unsigned char usb_kbd_keycode[256] = { +@@ -252,6 +311,8 @@ + struct semaphore lock; + char name[NAME_BUFSIZE]; + char phys[NAME_BUFSIZE]; ++ ++ unsigned int carrier_freq; + }; + + /* init strings */ +@@ -889,6 +950,51 @@ + } + } + ++/* Sets the send carrier frequency */ ++static int set_send_carrier(struct irctl *ir, int carrier) ++{ ++ int clk = 10000000; ++ int prescaler = 0, divisor = 0; ++ unsigned char cmdbuf[] = { 0x9F, 0x06, 0x01, 0x80 }; ++ ++ /* Carrier is changed */ ++ if (ir->carrier_freq != carrier) { ++ ++ if (carrier <= 0) { ++ ir->carrier_freq = carrier; ++ dprintk(DRIVER_NAME "[%d]: SET_CARRIER disabling " ++ "carrier modulation\n", ir->devnum); ++ request_packet_async(ir, ir->usb_ep_out, ++ cmdbuf, sizeof(cmdbuf), ++ PHILUSB_OUTBOUND); ++ return carrier; ++ } ++ ++ for (prescaler = 0; prescaler < 4; ++prescaler) { ++ divisor = (clk >> (2 * prescaler)) / carrier; ++ if (divisor <= 0xFF) { ++ ir->carrier_freq = carrier; ++ cmdbuf[2] = prescaler; ++ cmdbuf[3] = divisor; ++ dprintk(DRIVER_NAME "[%d]: SET_CARRIER " ++ "requesting %d Hz\n", ++ ir->devnum, carrier); ++ ++ /* Transmit new carrier to mce device */ ++ request_packet_async(ir, ir->usb_ep_out, ++ cmdbuf, sizeof(cmdbuf), ++ PHILUSB_OUTBOUND); ++ return carrier; ++ } ++ } ++ ++ return -EINVAL; ++ ++ } ++ ++ return carrier; ++} ++ + static int input_open(struct input_dev *id) + { + return 0; +@@ -945,6 +1051,18 @@ + if(lvalue!=(LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK)) return -EINVAL; + break; + ++ case LIRC_SET_SEND_CARRIER: ++ /* Retrieve lirc_plugin data for the device */ ++ ir=lirc_get_pdata(filep); ++ if (!ir && !ir->usb_ep_out) return -EFAULT; ++ ++ result = get_user(ivalue, (unsigned int *) arg); ++ if (result) ++ return result; ++ ++ set_send_carrier(ir, ivalue); ++ break; ++ + default: + return -ENOIOCTLCMD; + } +@@ -1047,7 +1165,8 @@ + plugin->minor = -1; + plugin->features = LIRC_CAN_SEND_PULSE | + LIRC_CAN_SET_TRANSMITTER_MASK | +- LIRC_CAN_REC_MODE2; ++ LIRC_CAN_REC_MODE2 | ++ LIRC_CAN_SET_SEND_CARRIER; + plugin->data = ir; + plugin->rbuf = rbuf; + plugin->set_use_inc = &set_use_inc; +@@ -1108,7 +1227,7 @@ + input_dev->name = ir->name; + input_dev->phys = ir->phys; + usb_to_input_id(dev, &input_dev->id); +- input_dev->cdev.dev = &dev->dev; ++ input_dev->dev.parent = &dev->dev; + input_dev->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); + input_dev->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); + input_dev->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X); |