changeset 1:05cc06e88a57

modified to make use of libhid to access the device
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Fri, 24 Dec 2010 15:28:04 +0900
parents e1a1a181c0d7
children b16b82dbfe87
files Makefile cdcnv.c rcctl.c
diffstat 3 files changed, 356 insertions(+), 318 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Thu Dec 16 20:30:11 2010 +0900
+++ b/Makefile	Fri Dec 24 15:28:04 2010 +0900
@@ -2,12 +2,17 @@
 
 TARGET = rcctl
 SRCS = rcctl.c cdcnv.c
+OBJS = rcctl.o cdcnv.o
 CC = gcc
-CCOPT = -O -lusb -Wall
 
-all:
-	$(CC) $(CCOPT) -o $(TARGET) $(SRCS)
+# for debug build
+CFLAGS = -O -Wall -g -DVERBOSE -DDEBUG -I/usr/include/libusb-1.0
+# for release build
+#CFLAGS = -O -Wall
+LDFLAGS = -lhid -lusb
 
-debug:
-	$(CC) $(CCOPT) -DVERBOSE -DDEBUG -o $(TARGET) $(SRCS)
+all: $(OBJS)
+	$(CC) -o $(TARGET) $(OBJS) $(LDFLAGS)
 
+clean:
+	rm -f *.o $(TARGET)
--- a/cdcnv.c	Thu Dec 16 20:30:11 2010 +0900
+++ b/cdcnv.c	Fri Dec 24 15:28:04 2010 +0900
@@ -11,11 +11,12 @@
 ------------------------------------------------------*/
 
 #include <string.h>
+#include <stdio.h>
 #if defined(__FreeBSD__)||defined(linux)
 #define stricmp(s, c) strcasecmp(s, c)
 #endif
 
-const char *mks = "XUGJHBPDSNKMALZTCI";
+const char mks[] = "XUGJHBPDSNKMALZTCI";
 #define M_X2 0	/* X2000 */
 #define M_UK 1	/* U-kara */
 #define M_GI 2	/* GIGA */
@@ -78,8 +79,10 @@
    0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f },
   {0x30, 0x00, 0xff, 0x41, 0x08, 0x09, 0x4c, 0x45, 0x44,      /* TOEI sys */
    0x13, 0x0f, 0x4f, 0x4e, 0x07, 0x47, 0x46, 0x03, 0x43, 0x42, 0x53, 0x52 },
+
   {0x10, 0x55, 0xaa, 0x3e, 0x08, 0x09, 0x5c,   -1,   -1,     /* Σ System */
    0x13, 0x0f, 0x4f, 0x4e, 0x07, 0x47, 0x46, 0x03, 0x43, 0x42, 0x53, 0x52 },
+
   {0x40, 0xae, 0x51, 0xdc, 0x03, 0x02, 0x96,   -1, 0xdd,          /* 鉄人 */
    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0xda, 0xdb }
   };
@@ -95,166 +98,174 @@
 
 int cdcnv(int buf[], char *mak, char *cod)
 {
-  int maker, i, c, n, *q;
+    int maker, i, c, n, *q;
+    char *tmp = NULL;
 
-  if ((maker = (int)strchr(mks, *mak & 0xdf)) == NULL)
-    return -1;
-  maker -= (int)mks;
+#ifdef DEBUG
+    fprintf(stderr, "mak=%s cod=%s\n", mak, cod);
+#endif
 
-  q = buf;
+    tmp = strchr(mks, *mak & 0xdf);
+    if(!tmp)
+        return -1;
+    maker = (int)(tmp - mks);
+#ifdef DEBUG
+    fprintf(stderr, "maker=%d\n", maker);
+#endif
+    q = buf;
 
-  *q++ = 0x80;	/* wake-up code */
-  *q++ = cvt[maker][0];
-  *q++ = cvt[maker][1];
-  *q++ = cvt[maker][2];
+    *q++ = 0x80;	/* wake-up code */
+    *q++ = cvt[maker][0];
+    *q++ = cvt[maker][1];
+    *q++ = cvt[maker][2];
 
-  /* 統合機種等でのメーカー名指定 */
-  if ((c = *++mak) != 0) {
-    if ((maker == M_A3)&&('0' <= c)&&(c <= '4'))
-      cvt[maker][K_SE] = 0x12 + (c - '0');
-    else if ((maker == M_AZ)&&('1' <= c)&&(c <= '4'))
-      *q++ = 0x13 + (c - '1');
-    else if ((maker == M_AL)&&('0' <= c)&&(c <= '9')) {
-      *q++ = cvt[maker][K_NM + (c - '0')];
-      *q++ = 0x10;
+    /* 統合機種等でのメーカー名指定 */
+    if ((c = *++mak) != 0) {
+        if ((maker == M_A3)&&('0' <= c)&&(c <= '4'))
+            cvt[maker][K_SE] = 0x12 + (c - '0');
+        else if ((maker == M_AZ)&&('1' <= c)&&(c <= '4'))
+            *q++ = 0x13 + (c - '1');
+        else if ((maker == M_AL)&&('0' <= c)&&(c <= '9')) {
+            *q++ = cvt[maker][K_NM + (c - '0')];
+            *q++ = 0x10;
+        }
+        else if ((maker == M_TS)&&('1' <= c)&&(c <= '8'))
+            *q++ = tsc[c - '1'];
+        else if ((maker == M_TJ)&&('0' <= c)&&(c <= '9'))
+            *q++ = tjc[c - '1'];
+        else if ((maker == M_UK)&&('2' == c)) {
+            buf[1] = 0x70;
+            *q++ = 0xf0;
+        }
     }
-    else if ((maker == M_TS)&&('1' <= c)&&(c <= '8'))
-      *q++ = tsc[c - '1'];
-    else if ((maker == M_TJ)&&('0' <= c)&&(c <= '9'))
-      *q++ = tjc[c - '1'];
-    else if ((maker == M_UK)&&('2' == c)) {
-      buf[1] = 0x70;
-      *q++ = 0xf0;
-    }
-  }
-  if (maker == M_BK)
-    *q++ = 0xf0;
+    if (maker == M_BK)
+        *q++ = 0xf0;
+
+    if (('0' <= *cod)&&(*cod <= '9')) {
+        if (maker == M_DA)
+            *q++ = 0x08;
+        else if (maker == M_MA)
+            *q++ = 0x10;	/* Req.1 */
+        else if (maker == M_SI) {
+            /* [1-9A-F] -> '01','02',...,'15' , NULL -> '00' */
+            if (*mak == 0) {
+                *q++ = cvt[maker][K_NM + 0];
+                *q++ = cvt[maker][K_NM + 0];
+            }
+            else {
+                if (mak[1] != 0)
+                    *q++ = cvt[maker][K_NM + (*mak++ - '0')];
+                else
+                    *q++ = cvt[maker][K_NM + ((*mak >= 'A')? 1: 0)];
+                *q++ = cvt[maker][K_NM + ((*mak % 0x41) & 0x0f)];
+            }
+        }
 
-  if (('0' <= *cod)&&(*cod <= '9')) {
-    if (maker == M_DA)
-      *q++ = 0x08;
-    else if (maker == M_MA)
-      *q++ = 0x10;	/* Req.1 */
-    else if (maker == M_SI) {
-      /* [1-9A-F] -> '01','02',...,'15' , NULL -> '00' */
-      if (*mak == 0) {
-        *q++ = cvt[maker][K_NM + 0];
-        *q++ = cvt[maker][K_NM + 0];
-      }
-      else {
-        if (mak[1] != 0)
-	  *q++ = cvt[maker][K_NM + (*mak++ - '0')];
-	else
-	  *q++ = cvt[maker][K_NM + ((*mak >= 'A')? 1: 0)];
-	*q++ = cvt[maker][K_NM + ((*mak % 0x41) & 0x0f)];
-      }
+        /* 曲コード変換 */
+        while((c = *cod++) != '\0') {
+            if (('0' <= c)&&(c <= '9'))
+                *q = cvt[maker][c - '0' + K_NM];
+            else if ((c == 'A')||(c == 'a'))
+                *q = cvt[maker][10 + K_NM];
+            else if ((c == 'B')||(c == 'b'))
+                *q = cvt[maker][11 + K_NM];
+            else if (c == '-') {
+                if (maker == M_TJ)
+                    *q = cvt[maker][K_SE];
+                else
+                    continue;
+            }
+            else
+                *q = -1;
+            if (*q++ == -1)
+                return -2;
+        }
+
+        /* 送信直前処理 */
+        switch(maker) {
+        case M_X2:
+            /* X2000: 曲コードの末尾 2 桁の直前にも SET を送信 */
+            q -= 2;
+            q[3] = cvt[maker][K_SE];
+            q[2] = q[1];
+            q[1] = q[0];
+            q[0] = cvt[maker][K_SE];
+            q += 4;
+            break;
+
+        case M_GI:
+            /* GIGA: 曲コードが 6 桁以下の場合は最後に'0'を埋める */
+            while(q < &buf[10])
+                *q++ = cvt[maker][K_NM];
+            break;
+
+        case M_PR:
+            /* Prologue21: */
+            for( i=0; i<3; i++ ) {
+                buf[10-i] = 0;
+                if (q > &buf[4])
+                    buf[10-i] = *--q << 4;
+                if (q > &buf[4])
+                    buf[10-i] |= *--q;
+            }
+            q = &buf[11];
+            *q++ = 0x33;
+            buf[4] = buf[8];
+            buf[5] = buf[9];
+            buf[6] = buf[10];
+            buf[7] = buf[11];
+            break;  /* q=&buf[8] にしないとバグのような… */
+
+        case M_SI:
+            /* Σシステム: コード長 10 バイト(<Maker[2]>,<Code[7]>,<SET>)固定 */
+        case M_DA:
+            /* DAM: コード長 9 バイト(0x08,<Code[7]>,<SET>)固定 */
+        case M_BK:
+            /* B-kara: コード長 9 バイト(0xf0,<Code[7]>,<SET>)固定 */
+            n = (maker == M_SI)? 12: 11; /* 数字の最終桁を buf[n] とした値 */
+            for( i=0; i<7; i++ ) {
+                c = *(q-1);
+                if ((i == 1)&&((c == cvt[maker][K_NM+10])||(c == cvt[maker][K_NM+11])))
+                    /* 曲コード中の'A','B'以降の桁数が1桁なら'0'を挿入 */
+                    buf[n-i] = cvt[maker][K_NM + 0];
+                else if ((i == 2)&&(c!=cvt[maker][K_NM+10])&&(c!=cvt[maker][K_NM+11]))
+                    /* 曲コードの末尾 3 文字めが'A','B'でなければ'-'を設定 */
+                    buf[n-i] = (maker == M_BK)? 0x3d: ((maker == M_SI)? 0x51: 0x3c);
+                else if (q > &buf[n-6])
+                    buf[n-i] = *--q;
+                else
+                    /* 桁数の足らない部分には'0'を設定 */
+                    buf[n-i] = cvt[maker][K_NM + 0];
+            }
+            q = &buf[n+1];
+        default:
+            *q++ = cvt[maker][K_SE];
+            break;
+        }
     }
-
-    /* 曲コード変換 */
-    while((c = *cod++) != '\0') {
-      if (('0' <= c)&&(c <= '9'))
-        *q = cvt[maker][c - '0' + K_NM];
-      else if ((c == 'A')||(c == 'a'))
-        *q = cvt[maker][10 + K_NM];
-      else if ((c == 'B')||(c == 'b'))
-        *q = cvt[maker][11 + K_NM];
-      else if (c == '-') {
-	if (maker == M_TJ)
-	  *q = cvt[maker][K_SE];
-	else
-	  continue;
-      }
-      else
+    /* 制御コードの処理 */
+    else {
         *q = -1;
-      if (*q++ == -1)
-	return -2;
+        if (!stricmp(cod, "SE"))
+            *q = cvt[maker][K_SE];
+        else if (!stricmp(cod, "KU"))
+            *q = cvt[maker][K_KU];
+        else if (!stricmp(cod, "KD"))
+            *q = cvt[maker][K_KD];
+        else if (!stricmp(cod, "SP"))
+            *q = cvt[maker][K_SP];
+        else if (!stricmp(cod, "ST"))
+            *q = cvt[maker][K_ST];
+        else if (!stricmp(cod, "CL"))
+            *q = cvt[maker][K_CL];
+        if (*q == -1)
+            return -3;
+        q++;
     }
 
-    /* 送信直前処理 */
-    switch(maker) {
-    case M_X2:
-      /* X2000: 曲コードの末尾 2 桁の直前にも SET を送信 */
-      q -= 2;
-      q[3] = cvt[maker][K_SE];
-      q[2] = q[1];
-      q[1] = q[0];
-      q[0] = cvt[maker][K_SE];
-      q += 4;
-      break;
-
-    case M_GI:
-      /* GIGA: 曲コードが 6 桁以下の場合は最後に'0'を埋める */
-      while(q < &buf[10])
-        *q++ = cvt[maker][K_NM];
-      break;
-
-    case M_PR:
-      /* Prologue21: */
-      for( i=0; i<3; i++ ) {
-        buf[10-i] = 0;
-        if (q > &buf[4])
-          buf[10-i] = *--q << 4;
-        if (q > &buf[4])
-          buf[10-i] |= *--q;
-      }
-      q = &buf[11];
-      *q++ = 0x33;
-      buf[4] = buf[8];
-      buf[5] = buf[9];
-      buf[6] = buf[10];
-      buf[7] = buf[11];
-      break;  /* q=&buf[8] にしないとバグのような… */
+    if ((maker == M_BK)||((maker == M_UK)&&('2' == *mak)))
+        *q++ = 0xf7;
 
-    case M_SI:
-      /* Σシステム: コード長 10 バイト(<Maker[2]>,<Code[7]>,<SET>)固定 */
-    case M_DA:
-      /* DAM: コード長 9 バイト(0x08,<Code[7]>,<SET>)固定 */
-    case M_BK:
-      /* B-kara: コード長 9 バイト(0xf0,<Code[7]>,<SET>)固定 */
-      n = (maker == M_SI)? 12: 11; /* 数字の最終桁を buf[n] とした値 */
-      for( i=0; i<7; i++ ) {
-        c = *(q-1);
-	if ((i == 1)&&((c == cvt[maker][K_NM+10])||(c == cvt[maker][K_NM+11])))
-	  /* 曲コード中の'A','B'以降の桁数が1桁なら'0'を挿入 */
-	  buf[n-i] = cvt[maker][K_NM + 0];
-        else if ((i == 2)&&(c!=cvt[maker][K_NM+10])&&(c!=cvt[maker][K_NM+11]))
-	  /* 曲コードの末尾 3 文字めが'A','B'でなければ'-'を設定 */
-          buf[n-i] = (maker == M_BK)? 0x3d: ((maker == M_SI)? 0x51: 0x3c);
-        else if (q > &buf[n-6])
-          buf[n-i] = *--q;
-        else
-	  /* 桁数の足らない部分には'0'を設定 */
-          buf[n-i] = cvt[maker][K_NM + 0];
-      }
-      q = &buf[n+1];
-    default:
-      *q++ = cvt[maker][K_SE];
-      break;
-    }
-  }
-  /* 制御コードの処理 */
-  else {
-    *q = -1;
-    if (!stricmp(cod, "SE"))
-      *q = cvt[maker][K_SE];
-    else if (!stricmp(cod, "KU"))
-      *q = cvt[maker][K_KU];
-    else if (!stricmp(cod, "KD"))
-      *q = cvt[maker][K_KD];
-    else if (!stricmp(cod, "SP"))
-      *q = cvt[maker][K_SP];
-    else if (!stricmp(cod, "ST"))
-      *q = cvt[maker][K_ST];
-    else if (!stricmp(cod, "CL"))
-      *q = cvt[maker][K_CL];
-    if (*q == -1)
-      return -3;
-    q++;
-  }
-
-  if ((maker == M_BK)||((maker == M_UK)&&('2' == *mak)))
-    *q++ = 0xf7;
-
-  buf[1] |= q-buf-2;	/* 実送信バイト数(PIC 制御用)を埋め込み */
-  return q-buf;
+    buf[1] |= q-buf-2;	/* 実送信バイト数(PIC 制御用)を埋め込み */
+    return q-buf;
 }
--- a/rcctl.c	Thu Dec 16 20:30:11 2010 +0900
+++ b/rcctl.c	Fri Dec 24 15:28:04 2010 +0900
@@ -1,207 +1,229 @@
 /* rcctl.c ---------------------------------------------
-$Id: rcctl.c,v 1.1 2002/12/21 01:13:28 tosy Exp $
+   $Id: rcctl.c,v 1.1 2002/12/21 01:13:28 tosy Exp $
 
-  v0.10  97.08.15  初期版(コミケット52)
-  v0.11  97.08.27  通信タイミング修正
-  v0.12  97.09.12  U-kara-2サポート
-  v0.12a 97.09.15  返り値設定
-  v0.12b 97.09.20  Bug fix (JOY:[SP])
-  v0.20  97.10.01  FreeBSD版
-  v0.20a 97.10.18  Bug fix (X2k:[SP],[ST])
-  v0.21  97.12.10  ALISA-3シーケンス修正
-  v0.30  97.12.13  コード変換部(cdcnv.c)分離
-  v0.40  02.12.16  USB版対応
-  【cdcnv.c の履歴も参照のこと】
-------------------------------------------------------*/
-
+   v0.10  97.08.15  初期版(コミケット52)
+   v0.11  97.08.27  通信タイミング修正
+   v0.12  97.09.12  U-kara-2サポート
+   v0.12a 97.09.15  返り値設定
+   v0.12b 97.09.20  Bug fix (JOY:[SP])
+   v0.20  97.10.01  FreeBSD版
+   v0.20a 97.10.18  Bug fix (X2k:[SP],[ST])
+   v0.21  97.12.10  ALISA-3シーケンス修正
+   v0.30  97.12.13  コード変換部(cdcnv.c)分離
+   v0.40  02.12.16  USB版対応
+   【cdcnv.c の履歴も参照のこと】
+   ------------------------------------------------------*/
+#define __LINUX__
 #include <fcntl.h>
 #include <stdio.h>
 #include <termios.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
+
+#define HID_MAX_USAGES 16
+typedef unsigned int __u32;
+typedef unsigned int kernel_ulong_t;
+
+#include <hid.h>
 #include <libusb.h>
-#include <sys/ioctl.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbhid.h>
 
-/* #define VERBOSE */
-/* #define NOCTSCHK */
+#include <linux/types.h>
+
+#define BITS_PER_LONG 32
 
-#ifndef SDEV
-#define SDEV "/dev/cuaa0"
+#include <asm/types.h>
+#include <errno.h>
+#include <string.h>
+
+
+#ifndef S_VERS
+#define S_VERS "0.41"
 #endif
 
-#ifndef UDEV
-#define UDEV "/dev/uhid0"
-#endif
+/* globals */
+HIDInterface *hidif;
+extern int errno;
 
-#ifndef S_VERS
-#define S_VERS "0.40"
-#endif
-
-int fd;
-
+/* prototypes */
 int cdcnv(int buf[], char *mak, char *cod);
 extern char *cverrstr[];
 
-int init_sio(void)
+int init_usb(void)
 {
-#ifndef NOCTSCHK
-  int tcnt = 0;
-#endif
-  struct termios tios;
-  int md;
+    hid_return ret;
+
+//    unsigned int report_id;
+//    unsigned int report_type;
+//    unsigned int size;
+
+    /* vendor id and product id of okecon */
+    HIDInterfaceMatcher matcher = { 0x0bfe, 0x2022, NULL, NULL, 0 };
+
+    /* see include/debug.h for possible values */
+    hid_set_debug(HID_DEBUG_ALL);
+    hid_set_debug_stream(stderr);
+    /* passed directly to libusb */
+    hid_set_usb_debug(0);
+
+    ret = hid_init();
+    if (ret != HID_RET_SUCCESS) {
+        fprintf(stderr, "hid_init failed with return code %d\n", ret);
+        return 1;
+    }
 
-  if ((fd = open(SDEV, O_RDWR)) == -1) {
-    fprintf(stderr, "Cannot open %s.\n", SDEV);
-    return 255;
-  }
+    hidif = hid_new_HIDInterface();
+    if (hidif == 0) {
+        fprintf(stderr, "hid_new_HIDInterface() failed, out of memory?\n");
+        return 1;
+    }
+
+    ret = hid_force_open(hidif, 0, &matcher, 3);
+    if (ret != HID_RET_SUCCESS) {
+        fprintf(stderr, "hid_force_open failed with return code %d\n", ret);
+        return 1;
+    }
 
-  tcgetattr(fd, &tios);
-  tios.c_iflag = 0;
-  tios.c_oflag = 0;
-  tios.c_cflag = B9600|CS8|CLOCAL;
-  tios.c_lflag = 0;
-/*
-  cfmakeraw(&tios);
-  cfsetspeed(&tios, B9600);
-*/
-  tcsetattr(fd, TCSANOW, &tios);
-  tcflush(fd, TCOFLUSH);
+
+
+#if 0
+    /* read feature */
+    ret = hid_get_feature_report(hidif, path, depth, buffer, size);
+    if(ret != HID_RET_SUCCESS) {
+        fprintf(stderr, "hid_get_feature_report failed with return code %d\n", ret);
+        return 1;
+    }
+
+    /* parse */
 
-  md = TIOCM_LE|TIOCM_DTR|TIOCM_RTS;
-  ioctl(fd, TIOCMBIS, &md);
+    /* prepare buffers */
+    hid_get_report_size(hidif, report_id, report_type, &size);
+    if(size != 8) {
+        fprintf(stderr, "%s is not 'OKCon/USB'?\n", UDEV);
+        return 1;
+    };
+
 
-  /* wait for CTS: 充電待ち */
-#ifndef NOCTSCHK
-  for(;;) {
-    ioctl(fd, TIOCMGET, &md);
-    if (md & TIOCM_CTS)
-      break;
-    if (tcnt == 0) {
-      fprintf(stderr, "Waiting....");
+// BSD
+    /* read header */
+    if ((rd = hid_get_report_desc(fd)) == 0) {
+        fprintf(stderr, "Failed on USB_GET_REPORT_DESC.\n");
+        return 1;
+    }
+
+    /* parse */
+    hd = hid_start_parse(rd, 1<<hid_output);
+    while ( hid_get_item(hd, &shi) ) {
+        if(shi.kind == hid_output)
+            break;
     }
-    if (tcnt++ >= 30) {
-      fprintf(stderr, "Device timeout.\n");
-      close(fd);
-      return 1;
+    hid_end_parse(hd);
+
+    /* prepare buffers */
+    hid_get_report_size(&hidif, report_id, report_type, &size);
+    if(size != 8) {
+        fprintf(stderr, "%s is not 'OKCon/USB'?\n", UDEV);
+        return 1;
+    };
+
+    hid_dispose_report_desc(rd);
+#endif
+
+    return 0;
+} /* end of init_usb() */
+
+
+int fin_usb()
+{
+    hid_return ret;
+
+    ret = hid_close(hidif);
+    if (ret != HID_RET_SUCCESS) {
+        fprintf(stderr, "hid_close failed with return code %d\n", ret);
+        return 1;
     }
-    sleep(1);
-  }
-#endif /* NOCTSCHK */
+
+    hid_delete_HIDInterface(&hidif);
 
-  md = TIOCM_RTS;
-  ioctl(fd, TIOCMBIC, &md);
-  usleep(10000);	/* 10ms */
-  ioctl(fd, TIOCMBIS, &md);
-  usleep(50000);	/* 50ms */
+    ret = hid_cleanup();
+    if (ret != HID_RET_SUCCESS) {
+        fprintf(stderr, "hid_cleanup failed with return code %d\n", ret);
+        return 1;
+    }
 
-  return 0;
+    return 0;
 }
 
-/* CTS が 0.5 秒以上連続して ON になるまで待つ */
-void charge(void)
-{
-#ifndef NOCTSCHK
-  int i, md;
 
-  for( i=0; i<50; i++ ) {
-    usleep(10000);	/* 10ms */
-    ioctl(fd, TIOCMGET, &md);
-    if (!(md & TIOCM_CTS))
-      i = 0;
-  }
-#endif /* NOCTSCHK */
-}
-
-int init_usb(void)
-{
-  report_desc_t rd;
-  hid_data_t hd;
-  hid_item_t shi;
-
-  hid_init(NULL);
-
-  if((fd = open(UDEV, O_RDWR)) < 0) {
-    fprintf(stderr, "Cannot open %s.\n", UDEV);
-    return 1;
-  }
-
-  /* read header */
-  if ((rd = hid_get_report_desc(fd)) == 0) {
-    fprintf(stderr, "Failed on USB_GET_REPORT_DESC.\n");
-    return 1;
-  }
-
-  /* parse */
-  hd = hid_start_parse(rd, 1<<hid_output);
-  while ( hid_get_item(hd, &shi) ) {
-    if(shi.kind == hid_output)
-      break;
-  }
-  hid_end_parse(hd);
-
-  /* prepare buffers */
-  if (hid_report_size(rd, hid_output, 0) != 8) {
-    fprintf(stderr, "%s is not 'OKCon/USB'?\n", UDEV);
-    return 1;
-  };
-
-  hid_dispose_report_desc(rd);
-
-  return 0;
-}
 
 int main(int ac, char *av[])
 {
-  int i, u, buf[16];
-  u_char sbuf[8];
+    int i, u, buf[16];
+    unsigned char sbuf[8];
+    hid_return ret;
 
-  if (ac < 3) {
-    printf("'Oke-Con' controller, version " S_VERS ".\n");
-    printf("Copyright (C) 1997-2002 by Tosy / W341IG.\n");
-    printf("Usage: rcctl <maker> <code>\n");
-    return 255;
-  }
+    if (ac < 3) {
+        printf("'Oke-Con' controller, version " S_VERS ".\n");
+        printf("Copyright (C) 1997-2002 by Tosy / W341IG.\n");
+        printf("Usage: rcctl <maker> <code>\n");
+        return 255;
+    }
 
-  if ((u = cdcnv(buf, av[1], av[2])) < 0) {
-    fprintf(stderr, "%s: %s\n", av[0], cverrstr[~u]);
-    return 1;
-  }
+    if ((u = cdcnv(buf, av[1], av[2])) < 0) {
+        fprintf(stderr, "%s: %s\n", av[0], cverrstr[~u]);
+        return 1;
+    }
+    printf("cdcnv %d\n", u);
 
 #ifdef VERBOSE
-  printf("Initializing....");
+    printf("Initializing....\n");
 #endif
-  if (init_usb())
-  /* if (init_sio()) */
-    return 255;
+
+    if (init_usb())
+        return 255;
+
 #ifdef VERBOSE
-  printf(" done.\n");
+    printf(" done.\n");
 #endif
 
 #ifdef VERBOSE
-/*  printf("maker %d (%c).\n", maker, mks[maker]); */
-  for(i=0; i<u; i++ ) {
-    printf("%02x ", buf[i]);
-  }
-  printf("\n");
+    for(i=0; i<u; i++ ) {
+        printf("%02x ", buf[i]);
+    }
+    printf("\n");
 #endif
 
-  for(i=1; i<u; i++ ) {
-    sbuf[(i-1)%8] = buf[i] & 0x00ff;
-#ifdef VERBOSE
-    printf("%02x ", sbuf[(i-1)%8]);
-#endif
-    if ((i == 8)||(i == (u-1))) {
-      write(fd, sbuf, 8);
+    /* xxx */
+	const int PATH_IN[1] = { 0xffa10004 };
+//    const int PATH_OUT[1] = { 0xffa10008 };
+
+    /* u is the total length of the packet to send */
+    for(i=1; i<u; i++ ) {
+        sbuf[(i-1)%8] = buf[i] & 0x00ff;
 #ifdef VERBOSE
-      printf(" --- got %d chars.\n", read(fd, sbuf, 8));
-#else
-      read(fd, sbuf, 8);
+        printf("%02x ", sbuf[(i-1)%8]);
 #endif
+        if ((i == 8)||(i == (u-1))) {
+            ret = hid_set_output_report(hidif, PATH_IN, 2, (char *)sbuf, 8);
+            fprintf(stderr, "**WRITE**\n");
+            if (ret != HID_RET_SUCCESS) {
+                fprintf(stderr, "hid_set_output_report failed with return code %d\n", ret);
+            }
+
+#if 0
+            char packet[8];
+            ret = hid_get_input_report(hidif, PATH_OUT, 2, packet, 8);
+            if (ret != HID_RET_SUCCESS) {
+                fprintf(stderr, "hid_get_input_report failed with return code %d\n", ret);
+            }
+#endif
+        }
     }
-  }
+#ifdef VERBOSE
+    printf("\n");
+#endif
 
-  /* charge(); */
-  close(fd);
-  return 0;
+    if(fin_usb())
+        return 255;
+
+    return 0;
 }