[Patch] Driver and configuration for the Philips SRM 7500 RF remote

View: New views
4 Messages — Rating Filter:   Alert me  

[Patch] Driver and configuration for the Philips SRM 7500 RF remote

by Henning Glawe :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Moin,
I am ready with my driver for the Philips SRM 7500 RF remote.
The driver is called srm7500libusb, usage instructions can be found in
remotes/philips/lircd.conf.srm7500libusb

Note: as dongle and the remote build a ieee 802.15.4 PAN, you have to specify
at least the three parameters for the PAN Id and the short addresses to be
assigned to the dongle and the remote.

--
c u
henning


diff -urN lirc-0.8.6/configure.ac lirc-0.8.6.srm7500libusb/configure.ac
--- lirc-0.8.6/configure.ac 2009-09-13 10:49:12.000000000 +0200
+++ lirc-0.8.6.srm7500libusb/configure.ac 2009-09-19 20:14:08.000000000 +0200
@@ -323,7 +323,7 @@
 
 if test -n "${LIBUSB_CONFIG}"; then
   AC_DEFINE(HAVE_LIBUSB)
-  possible_drivers="${possible_drivers} (atilibusb) (awlibusb) (commandir)"
+  possible_drivers="${possible_drivers} (atilibusb) (awlibusb) (commandir) (srm7500libusb)"
 fi
 
 AC_CHECK_LIB(caraca_client, caraca_init,
@@ -454,6 +454,7 @@
                           pixelview_pak, pixelview_pro, provideo,
                           realmagic, remotemaster, sa1100, samsung,
                           sasem, sb0540, serial, silitek, sir, slinke,
+  srm7500libusb,
                           streamzap, tekram, tekram_bt829, tira,
   ttusbir, tuxbox, tvbox, udp, uirt2,
   uirt2_raw, usb_uirt_raw, usbx, wpc8769l],
@@ -475,6 +476,7 @@
 alsa_lib=""
 atilibusb_lib=""
 awlibusb_lib=""
+srm7500libusb_lib=""
 hw_module="hw_default.o receive.o transmit.o"
 HW_DEFAULT="hw_default"
 kernel_module=""
@@ -669,6 +671,11 @@
  #slinke)
  #hw_module="${hw_module} hw_slinke.o serial.o receive.o"
  #;;
+ srm7500libusb)
+ hw_module="${hw_module} hw_srm7500libusb.o receive.o"
+ srm7500libusb_lib=`${LIBUSB_CONFIG} --libs`
+ CFLAGS="$CFLAGS `${LIBUSB_CONFIG} --cflags`"
+ ;;
  tira)
  hw_module="${hw_module} hw_tira.o"
  ;;
@@ -1325,6 +1332,17 @@
   HW_DEFAULT="hw_slinke"
 fi
 
+if test "$driver" = "srm7500libusb"; then
+  lirc_driver="$driver"
+  hw_module="hw_srm7500libusb.o receive.o"
+  HW_DEFAULT="hw_srm7500libusb"
+  lircd_conf="srm7500usb/lircd.conf.srm7500libusb"
+  if test -n "${LIBUSB_CONFIG}"; then
+    srm7500libusb_lib=`${LIBUSB_CONFIG} --libs`
+    CFLAGS="$CFLAGS `${LIBUSB_CONFIG} --cflags`"
+  fi
+fi
+
 if test "$driver" = "streamzap"; then
   lirc_driver="lirc_dev lirc_streamzap"
   lircd_conf="streamzap/lircd.conf.streamzap"
@@ -1426,7 +1444,7 @@
     AC_MSG_ERROR([*** you need to have the Linux kernel source installed
  for this driver])
     ;;
-  atilibusb|awlibusb|commandir)
+  atilibusb|awlibusb|commandir|srm7500libusb)
     AC_MSG_ERROR([*** you need to have libusb installed for this driver.
 
 Get it at:
@@ -1486,6 +1504,7 @@
  test "$lirc_driver" = "macmini" || \
  test "$lirc_driver" = "samsung" || \
  test "$lirc_driver" = "sb0540" || \
+ test "$lirc_driver" = "srm7500libusb" || \
  test "$lirc_driver" = "userspace"; then
   lirc_driver=
 elif test "$lirc_driver" = "all"; then
@@ -1667,7 +1686,7 @@
  receive="receive.o"
 fi
 
-hw_module_libs="${alsa_lib} ${atilibusb_lib} ${awlibusb_lib} ${caraca_lib} ${commandir_lib} ${ftdi_lib} ${iguanaIR_lib} ${irman_lib} ${portaudio_lib}"
+hw_module_libs="${alsa_lib} ${atilibusb_lib} ${awlibusb_lib} ${caraca_lib} ${commandir_lib} ${ftdi_lib} ${iguanaIR_lib} ${irman_lib} ${portaudio_lib} ${srm7500libusb_lib}"
 
 dnl tell the Makefiles what we decided
 AC_SUBST(daemon)
diff -urN lirc-0.8.6/daemons/hw_devinput.c lirc-0.8.6.srm7500libusb/daemons/hw_devinput.c
--- lirc-0.8.6/daemons/hw_devinput.c 2009-09-07 20:08:00.000000000 +0200
+++ lirc-0.8.6.srm7500libusb/daemons/hw_devinput.c 2009-09-21 21:27:09.000000000 +0200
@@ -61,7 +61,7 @@
 
 struct hardware hw_devinput=
 {
- "/dev/input/event0", /* "device" */
+ "/dev/input/event1", /* "device" */
  -1, /* fd (device) */
  LIRC_CAN_REC_LIRCCODE, /* features */
  0, /* send_mode */
diff -urN lirc-0.8.6/daemons/hw_srm7500libusb.c lirc-0.8.6.srm7500libusb/daemons/hw_srm7500libusb.c
--- lirc-0.8.6/daemons/hw_srm7500libusb.c 1970-01-01 01:00:00.000000000 +0100
+++ lirc-0.8.6.srm7500libusb/daemons/hw_srm7500libusb.c 2009-10-31 14:02:35.398115834 +0100
@@ -0,0 +1,921 @@
+/*      $Id: hw_srm7500libusb.c,v 5.5 2009/07/05 21:29:24 jarodwilson Exp $      */
+
+/****************************************************************************
+ ** hw_srm7500libusb.c ******************************************************
+ ****************************************************************************
+ *  Userspace (libusb) driver for Philips SRM7500 RF Remote.
+ *  
+ *  Copyright (C) 2009 Henning Glawe <glaweh@...>
+ *
+ *  based on Userspace (libusb) driver for ATI/NVidia/X10 RF Remote.
+ *
+ *  Copyright (C) 2004 Michael Gold <mgold@...>
+ *
+ *  and hw_devinput.c
+ *
+ *  Copyright (C) 2002 Oliver Endriss <o.endriss@...>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <usb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "hardware.h"
+#include "ir_remote.h"
+#include "lircd.h"
+#include "receive.h"
+
+#include "hw_srm7500libusb.h"
+
+#define CODE_BYTES 4
+#define USB_TIMEOUT (1000*60)
+#define CONTROL_BUFFERSIZE 128
+
+static int srm7500_init();
+static int srm7500_deinit();
+static char *srm7500_rec(struct ir_remote *remotes);
+static int srm7500_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 usb_read_loop(int fd);
+static struct usb_device *find_usb_device(void);
+static int find_device_endpoints(struct usb_device *dev);
+static int srm7500_initialize_802154_stack();
+static int philipsrf_input(philipsrf_incoming_t *buffer_in);
+static int philipsrf_output(philipsrf_outgoing_t buffer_out);
+
+struct hardware hw_srm7500libusb =
+{
+ NULL,                       /* default device */
+ -1,                         /* fd */
+ LIRC_CAN_REC_LIRCCODE,      /* features */
+ 0,                          /* send_mode */
+ LIRC_MODE_LIRCCODE,         /* rec_mode */
+ CODE_BYTES * CHAR_BIT,      /* code_length */
+ srm7500_init,               /* init_func */
+ NULL,                       /* config_func */
+ srm7500_deinit,             /* deinit_func */
+ NULL,                       /* send_func */
+ srm7500_rec,                /* rec_func */
+ srm7500_decode,             /* decode_func */
+ NULL,                       /* ioctl_func */
+ NULL,                       /* readdata */
+ "srm7500libusb"
+};
+
+typedef struct {
+ u_int16_t vendor;
+ u_int16_t product;
+} usb_device_id;
+
+/* table of compatible remotes -- from lirc_atiusb */
+static usb_device_id usb_remote_id_table[] = {
+ { 0x0471, 0x0617 }, /* Philips IEEE802.15.4 RF Dongle */
+ { 0, 0 } /* Terminating entry */
+};
+
+static struct usb_dev_handle *dev_handle = NULL;
+static struct usb_endpoint_descriptor *dev_ep_in = NULL, *dev_ep_out = NULL;
+static pid_t child = -1;
+static ir_code code;
+static int repeat_flag=0;
+static u_int8_t macShortAddress[2]       = {0, 0};
+static u_int8_t macPANId[2]              = {0, 0};
+static u_int8_t LogicalChannel           = 0x19;
+static u_int8_t remoteShortAddress[2]    = {0, 0};
+static u_int8_t remoteExtendedAddress[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+static int remoteExtendedAddressGiven = 0;
+static u_int8_t macBeaconPayload[64] = "PHILIPS";
+static int macBeaconPayloadGiven = 0;
+static int requested_usb_bus_number = -1;
+static int requested_usb_device_number = -1;
+
+/****/
+
+/* initialize driver -- returns 1 on success, 0 on error */
+static int srm7500_init()
+{
+ struct usb_device *usb_dev;
+ int pipe_fd[2] = { -1, -1 };
+ int res,i;
+ u_int8_t control_buffer[CONTROL_BUFFERSIZE];
+ int got_macShortAddress = 0;
+ int got_macPANId = 0;
+ int got_remoteShortAddress = 0;
+
+ logprintf(LOG_INFO, "Initializing Philips USB receiver");
+
+ if (hw.device == NULL) {
+ logprintf(LOG_ERR, "No device options supplied, please documentation in philips/lircd.conf.srm7500libusb!");
+ return(0);
+ } else {
+ char  *op_start,*op_end,*string_end;
+ op_start=hw.device;
+ string_end=strchr(hw.device,0);
+ while (op_start<string_end) {
+ int result;
+ op_end=strchrnul(op_start,',');
+ if (!strncmp(op_start,"macShortAddress=",16)) {
+ result=sscanf(op_start+16,"%hhx:%hhx",macShortAddress,macShortAddress+1);
+ if (result == 2) {
+ got_macShortAddress = 1;
+ } else {
+ logprintf(LOG_ERR, "Error parsing option macShortAddress");
+ }
+ } else if (!strncmp(op_start,"macPANId=",9)) {
+ result=sscanf(op_start+9,"%hhx:%hhx",
+ macPANId,macPANId+1);
+ if (result == 2) {
+ got_macPANId = 1;
+ } else {
+ logprintf(LOG_ERR, "Error parsing option macPANId");
+ }
+ } else if (!strncmp(op_start,"LogicalChannel=",15)) {
+ result=sscanf(op_start+15,"%hhx",
+ &LogicalChannel);
+ if (result == 1) {
+ if (LogicalChannel!=0x19)
+ logprintf(LOG_WARNING, "Warning: SRM7500 may not work on other channels than 0x19");
+ } else {
+ logprintf(LOG_ERR, "Error parsing option LogicalChannel");
+ }
+ } else if (!strncmp(op_start,"remoteShortAddress=",19)) {
+ result=sscanf(op_start+19,"%hhx:%hhx",
+ remoteShortAddress,remoteShortAddress+1);
+ if (result == 2) {
+ got_remoteShortAddress = 1;
+ } else {
+ logprintf(LOG_ERR, "Error parsing option remoteShortAddress");
+ }
+ } else if (!strncmp(op_start,"remoteExtendedAddress=",22)) {
+ result=sscanf(op_start+22,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+ remoteExtendedAddress,remoteExtendedAddress+1,
+ remoteExtendedAddress+2,remoteExtendedAddress+3,
+ remoteExtendedAddress+4,remoteExtendedAddress+5,
+ remoteExtendedAddress+6,remoteExtendedAddress+7);
+ if (result == 8) {
+ remoteExtendedAddressGiven = 1;
+ } else {
+ logprintf(LOG_ERR, "Error parsing option remoteExtendedAddress");
+ }
+ } else if (!strncmp(op_start,"macBeaconPayload=",17)) {
+ strncpy((char*)macBeaconPayload,op_start+17,op_end-(op_start+17));
+ macBeaconPayload[op_end-(op_start+17)]=0;
+ macBeaconPayloadGiven = 1;
+ } else if (!strncmp(op_start,"usb=",4)) {
+ result=sscanf(op_start+4,"%i:%i",
+ &requested_usb_bus_number,&requested_usb_device_number);
+ if (result == 2) {
+ LOGPRINTF(LOG_DEBUG, "got usb %i:%i",
+ requested_usb_bus_number,requested_usb_device_number);
+ got_remoteShortAddress = 1;
+ } else {
+ logprintf(LOG_ERR, "Error parsing option usb");
+ }
+ } else {
+ char erroroptionstring[op_end-op_start+1];
+ strncpy(erroroptionstring,op_start,op_end-op_start+1);
+ erroroptionstring[op_end-op_start]=0;
+ logprintf(LOG_WARNING, "Unparsable option: %s",erroroptionstring);
+ }
+ op_start=op_end+1;
+ }
+ }
+ if (! (got_remoteShortAddress && got_macPANId && got_macShortAddress)) {
+ logprintf(LOG_ERR,"Driver needs at least remoteShortAddress, macPANId and macShortAddress");
+ return(0);
+ }
+ if (!macBeaconPayloadGiven) {
+ if (gethostname((char*)(macBeaconPayload+7),64-7) != 0) {
+ logprintf(LOG_ERR,"Could not get hostname!");
+ exit(-1);
+ }
+ }
+
+ logprintf(LOG_INFO, "802.15.4 network parameters");
+ logprintf(LOG_INFO, "    macShortAddress %02hhx:%02hhx",
+ macShortAddress[0],macShortAddress[1]);
+ logprintf(LOG_INFO, "    macPANId %02hhx:%02hhx",
+ macPANId[0],macPANId[1]);
+ logprintf(LOG_INFO, "    LogicalChannel %02hhx",
+ LogicalChannel);
+ logprintf(LOG_INFO, "    remoteShortAddress %02hhx:%02hhx",
+ remoteShortAddress[0],remoteShortAddress[1]);
+ logprintf(LOG_INFO, "    macBeaconPayload %s",macBeaconPayload);
+ if (remoteExtendedAddressGiven) {
+ logprintf(LOG_INFO, "    Connectivity restricted to remoteExtendedAddress %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ remoteExtendedAddress[0],remoteExtendedAddress[1],
+ remoteExtendedAddress[2],remoteExtendedAddress[3],
+ remoteExtendedAddress[4],remoteExtendedAddress[5],
+ remoteExtendedAddress[6],remoteExtendedAddress[7]);
+ }
+
+ init_rec_buffer();
+
+ /* 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, "Could not open pipe: %s", strerror(errno));
+ return 0;
+ }
+ hw.fd = pipe_fd[0];
+
+ usb_dev = find_usb_device();
+ if (usb_dev == NULL)
+ {
+ logprintf(LOG_ERR, "Could not find a compatible USB device");
+ return 0;
+ }
+
+ if (!find_device_endpoints(usb_dev))
+ {
+ logprintf(LOG_ERR, "Could not find device endpoints");
+ return 0;
+ }
+
+ dev_handle = usb_open(usb_dev);
+ if (dev_handle == NULL)
+ {
+ logprintf(LOG_ERR, "Could not open USB receiver: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ res=usb_detach_kernel_driver_np(dev_handle, 0);
+ if ( (res < 0) && (res != -ENODATA) ) {
+ logprintf(LOG_ERR, "Could not detach kernel driver: %s",
+ strerror(errno));
+ goto fail;
+ }
+#endif
+
+ if (usb_claim_interface(dev_handle, 0) != 0)
+ {
+ logprintf(LOG_ERR, "Could not claim USB interface: %s",
+ strerror(errno));
+ goto fail;
+ }
+
+ errno = 0;
+
+ // Device initialization
+ for (i=0; i<CONTROL_BUFFERSIZE; i++)
+ control_buffer[i]=0;
+ usb_control_msg(dev_handle,
+ USB_TYPE_STANDARD|USB_RECIP_INTERFACE|USB_ENDPOINT_OUT,
+ USB_REQ_SET_INTERFACE,
+ 0x0000,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0000,
+ USB_TIMEOUT);
+ control_buffer[0]=0xe4;
+ usb_control_msg(dev_handle,
+ USB_TYPE_CLASS|USB_RECIP_INTERFACE|USB_ENDPOINT_OUT,
+ USB_REQ_SET_CONFIGURATION,
+ 0x0300,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0010,
+ USB_TIMEOUT);
+ control_buffer[0]=0;
+ usb_control_msg(dev_handle,
+ USB_TYPE_CLASS|USB_RECIP_INTERFACE|USB_ENDPOINT_IN,
+ USB_REQ_CLEAR_FEATURE,
+ 0x0300,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0010,
+ USB_TIMEOUT);
+ /*
+ HG: with this the red control light on usb receiver is switched on
+ seems like the command to enable transceiver
+ */
+ control_buffer[0]=0xe2;
+ for (i=1; i<CONTROL_BUFFERSIZE; i++)
+ control_buffer[i]=0;
+ usb_control_msg(dev_handle,
+ USB_TYPE_CLASS|USB_RECIP_INTERFACE|USB_ENDPOINT_OUT,
+ USB_REQ_SET_CONFIGURATION,
+ 0x0300,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0010,
+ USB_TIMEOUT);
+ for (i=0; i<CONTROL_BUFFERSIZE; i++)
+ control_buffer[i]=0;
+ usb_control_msg(dev_handle,
+ USB_TYPE_CLASS|USB_RECIP_INTERFACE|USB_ENDPOINT_IN,
+ USB_REQ_CLEAR_FEATURE,
+ 0x0300,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0010,
+ USB_TIMEOUT);
+ /*
+ *  HG: initialize 802.15.4 stack
+ */
+ srm7500_initialize_802154_stack();
+
+ child = fork();
+ if (child == -1)
+ {
+ logprintf(LOG_ERR, "Could not fork child process: %s",
+ strerror(errno));
+ goto fail;
+ }
+ else if (child == 0)
+ {
+ usb_read_loop(pipe_fd[1]);
+ }
+
+ logprintf(LOG_INFO, "USB receiver initialized");
+ return 1;
+
+fail:
+ if (dev_handle)
+ {
+ usb_close(dev_handle);
+ dev_handle = NULL;
+ }
+ if (pipe_fd[0] >= 0) close(pipe_fd[0]);
+ if (pipe_fd[1] >= 0) close(pipe_fd[1]);
+ return 0;
+}
+
+static int srm7500_initialize_802154_stack()
+{
+ philipsrf_outgoing_t packet_buffer_out;
+ philipsrf_incoming_t packet_buffer_in;
+
+ int i;
+ int outret,inret,err;
+ int tries=3;
+ int answer_received=0;
+ err=0;
+
+ while ((! answer_received) && (tries>0) ) {
+ inret=philipsrf_input(&packet_buffer_in);
+ if ((packet_buffer_in.type    == MLME_SET_confirm) &&
+ (packet_buffer_in.data[0] == 0) &&
+ (packet_buffer_in.data[1] == PIB_ATTR_macExtendedAddress))
+ answer_received=1;
+ tries--;
+ }
+ if ((tries==0) && (packet_buffer_in.type != MLME_SET_confirm))
+ goto fail;
+
+ packet_buffer_out.length  = 2;
+ packet_buffer_out.type    = MLME_RESET_request;
+ packet_buffer_out.data[0] = MLME_TRUE;   // SetDefaultPIB
+
+ outret=philipsrf_output(packet_buffer_out);
+ inret=philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_RESET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not reset USB dongle!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 4;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macCoordShort_Address;
+ packet_buffer_out.data[1] = macShortAddress[0];
+ packet_buffer_out.data[2] = macShortAddress[1];
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macCoordShort_Address!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 4;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macPANId;
+ packet_buffer_out.data[1] = macPANId[0];
+ packet_buffer_out.data[2] = macPANId[1];
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macPANId!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 4;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macShortAddress;
+ packet_buffer_out.data[1] = macShortAddress[0];
+ packet_buffer_out.data[2] = macShortAddress[1];
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macShortAddress!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 3;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macAssociation_Permit;
+ packet_buffer_out.data[1] = MLME_TRUE;
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macAssociation_Permit!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 3;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macRxOnWhenIdle;
+ packet_buffer_out.data[1] = MLME_TRUE;
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macRxOnWhenIdle!");
+ goto fail;
+ }
+
+
+ // beacon data:
+ // contents: ASCII PHILIPS + hostname
+ u_int8_t beacon_length=0;
+ beacon_length=(u_int8_t)strnlen((char*)macBeaconPayload,64);
+
+ // beacon data length
+ packet_buffer_out.length  = 3;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macBeaconPayload_Length;
+ packet_buffer_out.data[1] = beacon_length;
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macBeaconPayload_Length!");
+ goto fail;
+ }
+
+ // beacon data
+ packet_buffer_out.length  = 2 + beacon_length;
+ packet_buffer_out.type    = MLME_SET_request;
+ packet_buffer_out.data[0] = PIB_ATTR_macBeaconPayload;
+ for (i=0;i<beacon_length;i++)
+ packet_buffer_out.data[i+1]=macBeaconPayload[i];
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_SET_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not set macBeaconPayload!");
+ goto fail;
+ }
+
+ packet_buffer_out.length  = 6;
+ packet_buffer_out.type    = MLME_START_request;
+ packet_buffer_out.data[0] = macPANId[0];
+ packet_buffer_out.data[1] = macPANId[1];
+ packet_buffer_out.data[2] = LogicalChannel;
+ // note: the RFC lists three bytes StartTime here. strange.
+ packet_buffer_out.data[3] = 0xff;      // BeaconOrder/SuperframeOrder? both are listed in the rfc with 0-15 range
+ // so this could be the compression of both...
+ packet_buffer_out.data[4] = MLME_TRUE; // PANCoordinator
+ // In RFC, there is a bunch of other data for this primitive (Table 72), which will be interpreted as set to 0
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ if (!((packet_buffer_in.type == MLME_START_confirm) &&
+      (packet_buffer_in.data[0] == 0))) {
+ logprintf(LOG_ERR,"Could not start PAN!");
+ goto fail;
+ }
+
+ return err;
+
+fail:
+ return 1;
+
+}
+
+#ifdef DEBUG
+#define HEXDUMP(log_level, prefix, buf, len) \
+ if(log_level<=debug) hexdump(log_level, prefix, buf, len)
+#else
+#define HEXDUMP(log_level, prefix, buf, len)
+#endif
+
+#ifdef DEBUG
+static void hexdump(int log_level,char *prefix, u_int8_t *buf, int len)
+{
+ int i;
+ char str[1024];
+ int pos = 0;
+ if (prefix != NULL) {
+ strncpy(str,prefix,sizeof(str));
+ pos = strnlen(str,sizeof(str));
+ }
+ if (len>0) {
+ for (i = 0; i < len; i++) {
+ if (pos + 3 >= sizeof(str)) {
+ break;
+ }
+
+ if (!(i % 8)) {
+ str[pos++] = ' ';
+ }
+
+ sprintf(str + pos, "%02x ", buf[i]);
+
+ pos += 3;
+ }
+ } else {
+ strncpy(str+pos,"NO DATA",sizeof(str));
+ }
+ logprintf(log_level, "%s", str);
+}
+#endif
+
+static int philipsrf_input(philipsrf_incoming_t *buffer_in) {
+ int ret=0;
+ ret=usb_interrupt_read(dev_handle,dev_ep_in->bEndpointAddress,(char*)buffer_in,64,USB_TIMEOUT);
+ if (ret>0) {
+ LOGPRINTF(LOG_DEBUG,"in: time 0x%08x, length 0x%02x, type 0x%02x",
+ ((buffer_in->time[3]<<24) | (buffer_in->time[2]<<16) |
+     (buffer_in->time[1]<<8)  | (buffer_in->time[0])),
+ buffer_in->length,buffer_in->type);
+ HEXDUMP(LOG_DEBUG,"in  data:",buffer_in->data,buffer_in->length-1);
+ }
+ return(ret);
+}
+
+static int philipsrf_output(philipsrf_outgoing_t buffer_out) {
+ int ret=0;
+ LOGPRINTF(LOG_DEBUG,"out: length 0x%02x, type 0x%02x",
+ buffer_out.length,buffer_out.type);
+ HEXDUMP(LOG_DEBUG,"out data:", buffer_out.data,buffer_out.length-1);
+ ret=usb_interrupt_write(dev_handle,dev_ep_out->bEndpointAddress,(char*)&buffer_out,buffer_out.length+1,USB_TIMEOUT);
+ return(ret);
+}
+
+/* deinitialize driver -- returns 1 on success, 0 on error */
+static int srm7500_deinit()
+{
+ int err = 0;
+ u_int8_t control_buffer[CONTROL_BUFFERSIZE];
+ int i;
+
+ logprintf(LOG_INFO,"Disabling USB receiver");
+
+ if (dev_handle)
+ {
+ /*
+ HG: sending e1 as control payload disables the control light. so most probably the transceiver, too
+ */
+ control_buffer[0]=0xe1;
+ for (i=1; i<CONTROL_BUFFERSIZE; i++)
+ control_buffer[i]=0;
+ usb_control_msg(dev_handle,
+ USB_TYPE_CLASS|USB_RECIP_INTERFACE|USB_ENDPOINT_OUT,
+ USB_REQ_SET_CONFIGURATION,
+ 0x0300,
+ 0x0000,
+ (char*)control_buffer,
+ 0x0010,
+ USB_TIMEOUT);
+ usb_reset(dev_handle);
+ if (usb_close(dev_handle) < 0) err = 1;
+ dev_handle = NULL;
+ }
+
+ if (hw.fd >= 0)
+ {
+ if (close(hw.fd) < 0) err = 1;
+ hw.fd = -1;
+ }
+
+ if (child > 1)
+ {
+ if ( (kill(child, SIGTERM) == -1)
+ || (waitpid(child, NULL, 0) == 0) ) err = 1;
+ }
+
+ return !err;
+}
+
+static char *srm7500_rec(struct ir_remote *remotes)
+{
+ u_int8_t rccode[3];
+ int rd;
+
+ rd = read(hw.fd, &rccode, 3);
+ if (rd != 3) {
+ logprintf(LOG_ERR, "Error reading from usb worker process");
+ if(rd <= 0 && errno != EINTR) raise(SIGTERM);
+ return 0;
+ }
+
+ LOGPRINTF(LOG_DEBUG, "key %02d%02d, type %02d",
+ rccode[0],rccode[1],rccode[2]);
+
+ code = 0x80010000;
+ code |= ((rccode[0] << 8) | (rccode[1]));
+
+ repeat_flag = (rccode[2] == 2) ? 1:0;
+
+ LOGPRINTF(LOG_DEBUG, "code %.8llx", code);
+
+ if(rccode[2] == 3) return NULL;
+
+ return decode_all(remotes);
+}
+
+/* returns 1 if the given device should be used, 0 otherwise */
+static int is_device_ok(struct usb_device *dev)
+{
+ /* TODO: allow exact device to be specified */
+
+ /* check if the device ID is in usb_remote_id_table */
+ usb_device_id *dev_id;
+ for (dev_id = usb_remote_id_table; dev_id->vendor; dev_id++)
+ {
+ if ( (dev->descriptor.idVendor == dev_id->vendor) &&
+ (dev->descriptor.idProduct == dev_id->product) )
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* find a compatible USB receiver and return a usb_device,
+ * or NULL on failure. */
+static struct usb_device *find_usb_device(void)
+{
+ struct usb_bus *usb_bus;
+ struct usb_device *dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ if ((requested_usb_bus_number > 0) && (requested_usb_device_number > 0)) {
+ for (usb_bus=usb_busses;usb_bus; usb_bus=usb_bus->next)
+ if (atoi(usb_bus->dirname) == requested_usb_bus_number)
+ break;
+ if (! usb_bus) {
+ logprintf(LOG_ERR,"Requested USB bus %d does not exist",requested_usb_bus_number);
+ return NULL;
+ }
+ for (dev=usb_bus->devices;dev;dev=dev->next)
+ if (dev->devnum == requested_usb_device_number)
+ break;
+ if (! dev) {
+ logprintf(LOG_ERR,"Requested USB device %d:%d does not exist",requested_usb_bus_number,requested_usb_device_number);
+ return NULL;
+ }
+ if (is_device_ok(dev)) {
+ return dev;
+ } else {
+ logprintf(LOG_ERR,"Requested USB device %d:%d, but id %04x:%04x not handled by this driver",
+ requested_usb_bus_number,requested_usb_device_number,
+ dev->descriptor.idVendor,dev->descriptor.idProduct);
+ }
+ } else {
+ for (usb_bus = usb_busses; usb_bus; usb_bus = usb_bus->next)
+ {
+ for (dev = usb_bus->devices; dev; dev = dev->next)
+ {
+ if (is_device_ok(dev)) return dev;
+ }
+ }
+ }
+ return NULL;  /* no suitable device found */
+}
+
+/* set dev_ep_in and dev_ep_out to the in/out endpoints of the given
+ * device. returns 1 on success, 0 on failure. */
+static int find_device_endpoints(struct usb_device *dev)
+{
+ struct usb_interface_descriptor *idesc;
+ if (dev->descriptor.bNumConfigurations != 1) return 0;
+ if (dev->config[0].bNumInterfaces != 1) return 0;
+ if (dev->config[0].interface[0].num_altsetting != 1) return 0;
+
+ idesc = &dev->config[0].interface[0].altsetting[0];
+ if (idesc->bNumEndpoints != 2) return 0;
+
+ dev_ep_in = &idesc->endpoint[1];
+ if ((dev_ep_in->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ != USB_ENDPOINT_IN) return 0;
+ if ((dev_ep_in->bmAttributes & USB_ENDPOINT_TYPE_MASK)
+ != USB_ENDPOINT_TYPE_INTERRUPT) return 0;
+
+ dev_ep_out = &idesc->endpoint[0];
+ if ((dev_ep_out->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ != USB_ENDPOINT_OUT) return 0;
+ if ((dev_ep_out->bmAttributes & USB_ENDPOINT_TYPE_MASK)
+ != USB_ENDPOINT_TYPE_INTERRUPT) return 0;
+
+ return 1;
+}
+
+/* this function is run in a forked process to read data from the USB
+ * receiver and write it to the given fd. it calls exit() with result
+ * code 0 on success, or 1 on failure. */
+static void usb_read_loop(int fd)
+{
+ int err = 0;
+
+ alarm(0);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGALRM, SIG_IGN);
+
+ for(;;)
+ {
+ philipsrf_outgoing_t packet_buffer_out;
+ philipsrf_incoming_t packet_buffer_in;
+ int inret, outret;
+ int i;
+ int is_ok;
+ inret=philipsrf_input(&packet_buffer_in);
+ if (inret == -ETIMEDOUT)
+ continue;
+
+ if (inret < 0) {
+ logprintf(LOG_ERR,"Read error %d from usb dongle\n", inret);
+ }
+
+ switch (packet_buffer_in.type) {
+ case MLME_ASSOCIATE_indication:
+ // setting up the remote pc connection
+ //    in: 0b 47 869ef4bc453e9000 88                    10
+ //              DeviceAddress    CapabilityInformation SecurityLevel(3bit),KeyIdMode(2bit) KeySource KeyIndex
+ //   out: 0d 48 869ef4bc453e9000 0039               00      00
+ //              DeviceAddress    AssocShortAddress  status  SecurityLevel(3bit),KeyIdMode(2bit) KeySource KeyIndex
+ // first packet in setup
+
+ packet_buffer_out.length   =   13;
+ packet_buffer_out.type     = MLME_ASSOCIATE_response;
+ for (i=0;i<8;i++) {
+ packet_buffer_out.data[i]=packet_buffer_in.data[i];
+ }    // DeviceAddress, copied from indication
+ packet_buffer_out.data[8]  = remoteShortAddress[0];    // AssocShortAddress[0]
+ packet_buffer_out.data[9]  = remoteShortAddress[1];    // AssocShortAddress[1]
+
+ is_ok=1;
+ if (remoteExtendedAddressGiven)
+ for (i=0;i<8;i++)
+ if (packet_buffer_in.data[i] != remoteExtendedAddress[i])
+ is_ok=0;
+
+ if (is_ok) {
+ logprintf(LOG_NOTICE,"MLME_ASSOCIATE.response: device %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x associated",
+ packet_buffer_in.data[0],packet_buffer_in.data[1],
+ packet_buffer_in.data[2],packet_buffer_in.data[3],
+ packet_buffer_in.data[4],packet_buffer_in.data[5],
+ packet_buffer_in.data[6],packet_buffer_in.data[7]);
+ packet_buffer_out.data[10] =    0;    // Status: Successful
+ } else {
+ logprintf(LOG_NOTICE,"MLME_ASSOCIATE.response: unknown device %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x rejected",
+ packet_buffer_in.data[0],packet_buffer_in.data[1],
+ packet_buffer_in.data[2],packet_buffer_in.data[3],
+ packet_buffer_in.data[4],packet_buffer_in.data[5],
+ packet_buffer_in.data[6],packet_buffer_in.data[7]);
+ packet_buffer_out.data[10] = 0x02;    // Status: Access denied
+ }
+
+ packet_buffer_out.data[11] =    0;    // SecurityLevel,KeyIdMode
+ outret=philipsrf_output(packet_buffer_out);
+ inret=philipsrf_input(&packet_buffer_in);
+ if ((packet_buffer_in.type == MLME_COMM_STATUS_indication) &&
+ (packet_buffer_in.data[packet_buffer_in.length-2] == 0) ) {
+ }
+ break;
+ case MLME_ORPHAN_indication:
+ // after waking up remote:
+ //    in: 0a 52 869ef4bc453e9000 10
+ //              OrphanAddress    SecurityLevel(3bit),KeyIdMode(2bit) KeySource KeyIndex
+ //   out: 0c 53 869ef4bc453e9000 0039         01
+ //              OrphanAddress    ShortAddress AssociatedMember
+ //    in: 165ab59e 034a6100 0000eb0d 0003869e f4bc453e 900000
+ // authorizing the remote?
+ packet_buffer_out.length   =   12;
+
+ packet_buffer_out.type     = MLME_ORPHAN_response;
+
+ for (i=0;i<8;i++) {
+ packet_buffer_out.data[i]=packet_buffer_in.data[i];
+ }    // OrphanAddress, copied from indication
+
+ packet_buffer_out.data[8]  = remoteShortAddress[0];    // ShortAddress
+ packet_buffer_out.data[9]  = remoteShortAddress[1];
+
+ is_ok=1;
+ if (remoteExtendedAddressGiven)
+ for (i=0;i<8;i++)
+ if (packet_buffer_in.data[i] != remoteExtendedAddress[i])
+ is_ok=0;
+
+ if (is_ok) {
+ packet_buffer_out.data[10] = MLME_TRUE;    // AssociatedMember
+ } else {
+ logprintf(LOG_NOTICE,"MLME_ORPHAN.response: unknown device %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x rejected",
+ packet_buffer_in.data[0],packet_buffer_in.data[1],
+ packet_buffer_in.data[2],packet_buffer_in.data[3],
+ packet_buffer_in.data[4],packet_buffer_in.data[5],
+ packet_buffer_in.data[6],packet_buffer_in.data[7]);
+ packet_buffer_out.data[10] = MLME_FALSE;   // AssociatedMember
+ }
+
+ philipsrf_output(packet_buffer_out);
+ philipsrf_input(&packet_buffer_in);
+ break;
+ case MCPS_DATA_indication:
+ // nomal key on remote pressed
+ //   press: 1242  02 b59e 0027  02 b59e 4a61   04  00 00 46 01  ff 10
+ //  repeat: 1242  02 b59e 0027  02 b59e 4a61   04  00 00 46 02  ff 10
+ // release: 1242  02 b59e 0027  02 b59e 4a61   04  00 00 46 03  ff 10
+ LOGPRINTF(LOG_DEBUG,"MCPS_DATA_indication: Dest(0x%04x:%04x) Source(0x%04x:0x%04x)\n",
+ ((packet_buffer_in.zig.DstPANId[0]<<8) | (packet_buffer_in.zig.DstPANId[1])),
+ ((packet_buffer_in.zig.DstAddr[0]<<8)  | (packet_buffer_in.zig.DstAddr[1])),
+ ((packet_buffer_in.zig.SrcPANId[0]<<8) | (packet_buffer_in.zig.SrcPANId[1])),
+ ((packet_buffer_in.zig.SrcAddr[0]<<8)  | (packet_buffer_in.zig.SrcAddr[1]))
+ );
+ HEXDUMP(LOG_DEBUG,"MCPS_DATA_indication payload:",packet_buffer_in.zig.data,packet_buffer_in.zig.msduLength);
+ if ((packet_buffer_in.zig.data[0]==0x00) && (packet_buffer_in.zig.msduLength==4)) {
+ int bytes_w, pos;
+ for (pos = 1; pos < packet_buffer_in.zig.msduLength; pos += bytes_w)
+ {
+ bytes_w = write(fd, packet_buffer_in.zig.data + pos, packet_buffer_in.zig.msduLength - pos);
+ if (bytes_w < 0)
+ {
+ logprintf(LOG_ERR, "Could not write to pipe: %s",
+ strerror(errno));
+ err = 1; goto done;
+ }
+ }
+ }
+ break;
+ default:
+ logprintf(LOG_INFO,"Unhandled incoming usb packet 0x%02x\n",packet_buffer_in.type);
+ }
+ }
+
+done:
+ if (!usb_close(dev_handle)) err = 1;
+ _exit(err);
+}
+
+int srm7500_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)
+{
+ LOGPRINTF(LOG_DEBUG, "srm7500_decode");
+
+ if(!map_code(remote,prep,codep,postp,
+ 0,0,hw_srm7500libusb.code_length,code,0,0))
+ {
+ return(0);
+ }
+
+ *repeat_flagp       = repeat_flag;
+ *min_remaining_gapp = 0;
+ *max_remaining_gapp = 0;
+
+ return 1;
+}
diff -urN lirc-0.8.6/daemons/hw_srm7500libusb.h lirc-0.8.6.srm7500libusb/daemons/hw_srm7500libusb.h
--- lirc-0.8.6/daemons/hw_srm7500libusb.h 1970-01-01 01:00:00.000000000 +0100
+++ lirc-0.8.6.srm7500libusb/daemons/hw_srm7500libusb.h 2009-10-05 00:24:31.000000000 +0200
@@ -0,0 +1,61 @@
+#ifndef __HW_SRM7500LIBUSB_H__
+#define __HW_SRM7500LIBUSB_H__
+
+//USB stuff
+#define PACKET_SIZE_MAX 64
+
+//packet types
+#define MCPS_DATA_indication      0x42
+#define MLME_ASSOCIATE_indication 0x47
+#define MLME_ASSOCIATE_response   0x48
+#define MLME_ORPHAN_indication    0x52
+#define MLME_ORPHAN_response      0x53
+#define MLME_RESET_request        0x54
+#define MLME_RESET_confirm        0x55
+#define MLME_COMM_STATUS_indication  0x5a
+#define MLME_SET_request          0x5b
+#define MLME_SET_confirm          0x5c
+#define MLME_START_request        0x5d
+#define MLME_START_confirm        0x5e
+
+#define PIB_ATTR_macCoordShort_Address   0x4b
+#define PIB_ATTR_macExtendedAddress      0x6f
+#define PIB_ATTR_macPANId                0x50
+#define PIB_ATTR_macShortAddress         0x53
+#define PIB_ATTR_macAssociation_Permit   0x41
+#define PIB_ATTR_macRxOnWhenIdle         0x52
+#define PIB_ATTR_macBeaconPayload_Length 0x46
+#define PIB_ATTR_macBeaconPayload        0x45
+
+#define MLME_TRUE  1
+#define MLME_FALSE 0
+
+#pragma pack(1)
+typedef struct {
+ u_int8_t   time[4];
+ u_int8_t   length;
+ u_int8_t   type;
+ union {
+ struct {
+ u_int8_t  SrcAddrMode;
+ u_int8_t  SrcPANId[2];
+ u_int8_t  SrcAddr[2];   //Note: only valid for SrcAddrMode==0x02
+ u_int8_t  DstAddrMode;
+ u_int8_t  DstPANId[2];
+ u_int8_t  DstAddr[2];   //Note: only valid for DstAddrMode==0x02
+ u_int8_t  msduLength;   // <= aMaxMACFrameSize, so it is most probably one byte
+ u_int8_t  data[PACKET_SIZE_MAX-6-10];
+ } zig;
+ u_int8_t data[PACKET_SIZE_MAX-6];
+ };
+} philipsrf_incoming_t;
+
+typedef struct {
+ u_int8_t   length;
+ u_int8_t   type;
+ union {
+ u_int8_t data[PACKET_SIZE_MAX-2];
+ };
+} philipsrf_outgoing_t;
+#pragma pack()
+#endif
diff -urN lirc-0.8.6/daemons/hw-types.c lirc-0.8.6.srm7500libusb/daemons/hw-types.c
--- lirc-0.8.6/daemons/hw-types.c 2008-12-30 22:25:09.000000000 +0100
+++ lirc-0.8.6.srm7500libusb/daemons/hw-types.c 2009-09-20 11:53:50.000000000 +0200
@@ -43,6 +43,7 @@
 extern struct hardware hw_sb0540;
 extern struct hardware hw_silitek;
 extern struct hardware hw_slinke;
+extern struct hardware hw_srm7500libusb;
 extern struct hardware hw_tira;
 extern struct hardware hw_udp;
 extern struct hardware hw_uirt2;
@@ -151,6 +152,9 @@
  &hw_sb0540,
 #endif
  &hw_silitek,
+#ifdef HAVE_LIBUSB
+ &hw_srm7500libusb,
+#endif
  /* &hw_slinke,*/
  &hw_tira,
  &hw_udp,
diff -urN lirc-0.8.6/daemons/Makefile.am lirc-0.8.6.srm7500libusb/daemons/Makefile.am
--- lirc-0.8.6/daemons/Makefile.am 2009-07-25 17:30:57.000000000 +0200
+++ lirc-0.8.6.srm7500libusb/daemons/Makefile.am 2009-09-20 12:40:50.000000000 +0200
@@ -48,6 +48,7 @@
  hw_pixelview.c hw_pixelview.h \
  hw_silitek.c hw_silitek.h \
  hw_slinke.c hw_slinke.h \
+ hw_srm7500libusb.c hw_srm7500libusb.h \
  hw_tira.c hw_tira.h \
  hw_udp.c \
  hw_uirt2.c hw_uirt2_raw.c \
diff -urN lirc-0.8.6/remotes/philips/lircd.conf.srm7500libusb lirc-0.8.6.srm7500libusb/remotes/philips/lircd.conf.srm7500libusb
--- lirc-0.8.6/remotes/philips/lircd.conf.srm7500libusb 1970-01-01 01:00:00.000000000 +0100
+++ lirc-0.8.6.srm7500libusb/remotes/philips/lircd.conf.srm7500libusb 2009-10-31 14:05:34.806115449 +0100
@@ -0,0 +1,101 @@
+# Philips SRM-7500 RF configuration for use with the srm7500libusb driver
+#
+# The remote and the dongle communicate with each other over ieee 802.15.4
+# a few extra network parameters are needed (via lircd's --device option).
+#
+# lircd --driver=srm7500libusb lircd.conf.srm7500libusb \
+#       --device=macShortAddress=12:34,remoteShortAddress=56:78,macPANId=9a:bc
+#
+# explanation:
+#   mandatory parameters:
+#     macShortAddress:       802.15.4 short address (2 byte hex)
+#                            to be assigned to the receiver
+#     remoteShortAddress:    802.15.4 short address (2 byte hex)
+#                            to be assigned to the remote
+#     macPANId:              802.15.4 numeric network id (2 byte hex)
+#   optional parameters:
+#     remoteExtendedAddress: 802.15.4 extended address (8 byte hex)
+#                            of the remote. when given, ignores all other
+#                            802.15.4 rf communication. lircd writes your
+#                            remotes address to the logs when pairing
+#     macBeaconPayload:      802.15.4 network name  (ASCII string)
+#                            defaults to PHILIPS+your hostname. remote will not
+#                            pair unless it starts with PHILIPS.
+#     LogicalChannel:        802.15.4 channel number (1 byte hex)
+#                            defaults to 19
+#                            other channels than 19 do not work on my remote
+#     usb:                   USB bus and device number (2 integer decimal)
+#                            bind to a specific USB device, e.g. 003:002
+#
+# Things that work using this driver:
+#     - pairing
+#     - reception of all keypresses except for the 'music' button
+# Things that do not work yet
+#     - signal strength monitoring (via 'rf settings' in the remotes setup menu)
+#     - displaying infos on the remote's display
+#  
+
+begin remote
+
+  name  SRM-7500
+  bits           16
+  eps            30
+  aeps          100
+
+  one             0     0
+  zero            0     0
+  pre_data_bits   16
+  pre_data        0x8001
+  gap             132799
+  toggle_bit_mask 0x0
+
+      begin codes
+          Power                    0x0035
+          Back                     0x0024
+          More                     0x0033
+          Up                       0x0023
+          Down                     0x0011
+          Left                     0x0029
+          Right                    0x0031
+          Ok                       0x0039
+          Vol+                     0x0027
+          Vol-                     0x002A
+          Mute                     0x0028
+          Ch+                      0x0037
+          Ch-                      0x003A
+          Windows                  0x0015
+          Rec                      0x0012
+          Stop                     0x0017
+          Rew                      0x0007
+          Play                     0x001A
+          Fwd                      0x0047
+          Prev                     0x000A
+          Pause                    0x0016
+          Next                     0x004A
+          Guide                    0x0022
+          LiveTV                   0x0036
+          RecTV                    0x0026
+          DVD                      0x0032
+          1                        0x0008
+          2                        0x0018
+          3                        0x0048
+          4                        0x0009
+          5                        0x0019
+          6                        0x0049
+          7                        0x0004
+          8                        0x0014
+          9                        0x0044
+          Star                     0x0003
+          0                        0x0013
+          Hash                     0x0043
+          Text                     0x0042
+          Clear                    0x0001
+          Enter                    0x0041
+          AspectRatio              0x0006
+          Red                      0x0005
+          Green                    0x0002
+          Yellow                   0x0045
+          Blue                     0x0046
+      end codes
+
+end remote
diff -urN lirc-0.8.6/setup-driver.sh lirc-0.8.6.srm7500libusb/setup-driver.sh
--- lirc-0.8.6/setup-driver.sh 2009-09-13 10:52:29.000000000 +0200
+++ lirc-0.8.6.srm7500libusb/setup-driver.sh 2009-09-19 20:02:49.000000000 +0200
@@ -291,7 +291,8 @@
  t "USB-UIRT" \
  u "VLSystem MPlay Blast" \
  v "VLSystem MPlay Mini" \
- w "Windows Media Center Transceivers/Remotes (all)" 2> $TEMP
+ w "Windows Media Center Transceivers/Remotes (all)" \
+ x "Philips SRM 7500" 2> $TEMP
             if test "$?" = "0"; then
                 {
                 set `cat $TEMP`
@@ -329,6 +330,7 @@
                 elif test "$1" = "u"; then LIRC_DRIVER=mplay; DRIVER_PARAMETER=ttyUSB1; DRIVER_PARAM_TYPE=ttyUSB;
                 elif test "$1" = "v"; then LIRC_DRIVER=mplay; DRIVER_PARAMETER=ttyUSB1; DRIVER_PARAM_TYPE=ttyUSB;
                 elif test "$1" = "w"; then LIRC_DRIVER=mceusb; DRIVER_PARAMETER=none; DRIVER_PARAM_TYPE=none;
+                elif test "$1" = "x"; then LIRC_DRIVER=srm7500libusb; DRIVER_PARAMETER=none; DRIVER_PARAM_TYPE=none;
                 fi
                 }
                 else


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference

Re: [Patch] Driver and configuration for the Philips SRM 7500 RF remote

by Christoph Bartelmus :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi!

Henning Glawe "glaweh@..." wrote:
[...]
> +static char *srm7500_rec(struct ir_remote *remotes)
> +{
> + u_int8_t rccode[3];
> + int rd;
> +
> + rd = read(hw.fd, &rccode, 3);
> + if (rd != 3) {
> + logprintf(LOG_ERR, "Error reading from usb worker process");
> + if(rd <= 0 && errno != EINTR) raise(SIGTERM);

Instead of raise(SIGTERM), call srm7500_deinit() here.

> + return 0;
> + }
> +
> + LOGPRINTF(LOG_DEBUG, "key %02d%02d, type %02d",
> + rccode[0],rccode[1],rccode[2]);
> +
> + code = 0x80010000;

Get rid of this 0x8001 constant. It's meaningless.
Just remove pre_data and pre_data_bits from the config file.

> + code |= ((rccode[0] << 8) | (rccode[1]));
> +
> + repeat_flag = (rccode[2] == 2) ? 1:0;
> +
> + LOGPRINTF(LOG_DEBUG, "code %.8llx", code);
> +
> + if(rccode[2] == 3) return NULL;

What's the meaning of '3'?
Would it make sense to add the rccode[2] field to the code?


> + return decode_all(remotes);
> +}

Christoph

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference

Re: [Patch] Driver and configuration for the Philips SRM 7500 RF remote

by Henning Glawe :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

>On Sat, Oct 31, 2009 at 15:32:00PM +0100, Christoph wrote:
>Henning Glawe "glaweh@..." wrote:
>> + logprintf(LOG_ERR, "Error reading from usb worker process");
>> + if(rd <= 0 && errno != EINTR) raise(SIGTERM);
>
>Instead of raise(SIGTERM), call srm7500_deinit() here.

changed in new version of the driver. But: if we do not kill lircd at this
point, how can clients recover? if any client is still attached to lircd, the
receiver will not be reinitialized...


>> + code = 0x80010000;
>
>Get rid of this 0x8001 constant. It's meaningless.
>Just remove pre_data and pre_data_bits from the config file.

done. actually, this was a remainder of the hw_devinput code I forgot to
clean up.


>> + if(rccode[2] == 3) return NULL;
>
>What's the meaning of '3'?

it is the key-up event sent by the remote. documented in new version of the
driver (by introducing named constants).


>Would it make sense to add the rccode[2] field to the code?

I am not sure; rccode[2]==1 means button press, rccode[2]==2 means key repeat
(which the driver treats like in devinput by communicating the repeat flag
via a global variable to srm7500_decode). rccode[2]==3 is generated when a
key is released, so this could serve for an '_UP' event, while the other two
cases should map to the same key, once with and once without repeat flag.


--
c u
henning

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference

Re: [Patch] Driver and configuration for the Philips SRM 7500 RF remote

by Christoph Bartelmus :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi!

Henning Glawe "glaweh@..." wrote:

>> On Sat, Oct 31, 2009 at 15:32:00PM +0100, Christoph wrote:
>> Henning Glawe "glaweh@..." wrote:
>>> + logprintf(LOG_ERR, "Error reading from usb worker process");
>>> + if(rd <= 0 && errno != EINTR) raise(SIGTERM);
>>
>> Instead of raise(SIGTERM), call srm7500_deinit() here.

> changed in new version of the driver. But: if we do not kill lircd at this
> point, how can clients recover? if any client is still attached to lircd,
> the receiver will not be reinitialized...

The receiver will be reinitialized automatically by lircd.
Just try disconnecting and reconnecting the receiver. With all of my  
devices it will continue to work just as if nothing had happened.

>>> + if(rccode[2] == 3) return NULL;
>>
>> What's the meaning of '3'?

> it is the key-up event sent by the remote. documented in new version of the
> driver (by introducing named constants).

>> Would it make sense to add the rccode[2] field to the code?

> I am not sure; rccode[2]==1 means button press, rccode[2]==2 means key
> repeat (which the driver treats like in devinput by communicating the repeat
> flag via a global variable to srm7500_decode). rccode[2]==3 is generated
> when a key is released, so this could serve for an '_UP' event, while the
> other two cases should map to the same key, once with and once without
> repeat flag.

Ok, then make the config 24 bit and add all fields of rccode.
Map rccode[2]==2 to 1 after setting the repeat flag.
Then you can also add _UP events to the config file.
You can just take your current 16 bit config file, add post_data_bits=8,  
post_data=0x01. Then you can make a copy of the config and change  
post_data to 0x03.

Christoph


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference