Mercurial > rcctl_linux
changeset 0:e1a1a181c0d7
initial import
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Thu, 16 Dec 2010 20:30:11 +0900 |
parents | |
children | 05cc06e88a57 |
files | Makefile cdcnv.c rcctl.c |
diffstat | 3 files changed, 480 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Dec 16 20:30:11 2010 +0900 @@ -0,0 +1,13 @@ +# $Id: Makefile,v 1.1 2002/12/21 01:13:27 tosy Exp $ + +TARGET = rcctl +SRCS = rcctl.c cdcnv.c +CC = gcc +CCOPT = -O -lusb -Wall + +all: + $(CC) $(CCOPT) -o $(TARGET) $(SRCS) + +debug: + $(CC) $(CCOPT) -DVERBOSE -DDEBUG -o $(TARGET) $(SRCS) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdcnv.c Thu Dec 16 20:30:11 2010 +0900 @@ -0,0 +1,260 @@ +/* cdcnv.c --------------------------------------------- +$Id: cdcnv.c,v 1.1 2002/12/21 01:13:27 tosy Exp $ + + (以前の履歴は rcctl.c 参照) + v0.30 97.12.13 コード変換部(cdcnv.c)分離 + v0.31 98.03.07 Mac21対応 + v0.31a 98.03.11 Syncom対応(要rc_send修正) + v0.31b 98.03.15 ALISA3(L)対応 + v0.32 98.11.29 鉄人,Σ,NET7000対応 + v0.40 02.12.15 B-kara,HyperJOY対応,Σバグ修正 +------------------------------------------------------*/ + +#include <string.h> +#if defined(__FreeBSD__)||defined(linux) +#define stricmp(s, c) strcasecmp(s, c) +#endif + +const char *mks = "XUGJHBPDSNKMALZTCI"; +#define M_X2 0 /* X2000 */ +#define M_UK 1 /* U-kara */ +#define M_GI 2 /* GIGA */ +#define M_JO 3 /* JOYSOUND */ +#define M_HJ 4 /* HyperJOY */ +#define M_BT 5 /* BeMax'S(T) */ +#define M_PR 6 /* Prologue21 */ +#define M_DA 7 /* DAM */ +#define M_SY 8 /* Syncom/孫悟空 */ +#define M_N7 9 /* NET7000 */ +#define M_BK 10 /* B-kara */ +#define M_MA 11 /* Mac21 */ +#define M_A3 12 /* ALISA3(A) */ +#define M_AL 13 /* ALISA3(L) */ +#define M_AZ 14 /* ALISA3(Z) */ +#define M_TS 15 /* 東映システム */ +#define M_SI 16 /* Σシステム */ +#define M_TJ 17 /* カラオケの鉄人 */ + +#define K_SE 3 +#define K_KU 4 +#define K_KD 5 +#define K_SP 6 +#define K_ST 7 +#define K_CL 8 +#define K_NM 9 + +int cvt[][21] = { + /* cd, IDL, IDH, SE, KU, KD, SP, ST, CL, */ + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B*/ + {0x30, 0x2e, 0xd1, 0x17, 0x02, 0x03, 0x0c, 0x1c, 0x0d, /* X2000 */ + 0x13, 0x10, 0x14, 0x18, 0x11, 0x15, 0x19, 0x12, 0x16, 0x1a, -1, -1 }, + {0x30, 0x98, 0x67, 0x0c, 0x13, 0x12, 0x0f, 0x0e, 0x0d, /* U-kara/-2 */ + 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, -1, -1 }, + {0x10, 0x84, 0x10, -1, 0x04, 0x05, 0x0f, 0x01, -1, /* GIGA */ + 0xf0, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, -1, -1 }, + {0x40, 0x81, 0x16, 0x1f, 0x54, 0x0b, 0x1d, 0x5c, 0x1c, /* JOYSOUND */ + 0x00, 0x07, 0x0a, 0x58, 0x03, 0x06, 0x50, 0x01, 0x0e, 0x5d, -1, -1 }, + {0x20, 0x81, 0x16, 0x1f, 0x54, 0x0b, 0x1d, 0x5c, 0x1c, /* HyperJOY */ + 0x00, 0x07, 0x0a, 0x58, 0x03, 0x06, 0x50, 0x01, 0x0e, 0x5d, -1, -1 }, + {0x20, 0xac, 0x53, 0x9d, 0xcc, 0xca, 0x96, 0xdc, 0x9a, /* BeMax'S (T) */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, -1, -1 }, + {0x10, 0x81, 0xb0, 0x33, 0xd3, 0xb3, 0x93, 0x13, -1, /* Prologue21 */ + 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09, -1, -1 }, + {0x10, 0xd1, 0x2d, 0x09, 0x04, 0x05, 0x00, 0x01, 0x07, /* DAM */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b }, + {0x60, 0xc3, 0xc3, 0x05, 0x2c, 0x2d, 0x04, 0xc7, 0x02, /* Syncom */ + 0x0f, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, -1, -1 }, + {0x30, 0x84, 0x05, 0x0f, 0x0e, 0x0c, 0x07, -1, 0x1e, /* NET7000 */ + 0x1c, 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1a, -1, -1 }, + {0x10, 0x2e, 0xd1, 0x4c, 0x35, 0x33, 0x4f, 0x4e, 0x4d, /* B-kara */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b }, + {0x30, 0x80, 0x00, 0x03, 0x18, 0x14, 0x1e, -1, 0x07, /* Mac21 */ + 0x00, 0x0c, 0x0d, 0x0e, 0x08, 0x09, 0x0a, 0x04, 0x05, 0x06, 0x01, 0x02 }, + {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11, -1, 0x42, /* ALISA3 */ + 0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f }, + {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11, -1, 0x42, /* ALISA3 */ + 0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f }, + {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11, -1, 0x42, /* ALISA3 */ + 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 } + }; + +int tsc[] = {0x00, 0x04, 0x0c, 0x10, 0x01, 0x05, 0x0d, 0x11}; +int tjc[] = {0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xde, 0xd0, 0xd1, 0xd2, 0xd3}; + +char *cverrstr[] = { + "Invalid maker code.", + "Invalid music number.", + "Invalid function code." +}; + +int cdcnv(int buf[], char *mak, char *cod) +{ + int maker, i, c, n, *q; + + if ((maker = (int)strchr(mks, *mak & 0xdf)) == NULL) + return -1; + maker -= (int)mks; + + q = buf; + + *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; + } + 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 (('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; + } + } + /* 制御コードの処理 */ + 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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rcctl.c Thu Dec 16 20:30:11 2010 +0900 @@ -0,0 +1,207 @@ +/* rcctl.c --------------------------------------------- +$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 の履歴も参照のこと】 +------------------------------------------------------*/ + +#include <fcntl.h> +#include <stdio.h> +#include <termios.h> +#include <unistd.h> +#include <libusb.h> +#include <sys/ioctl.h> +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> + +/* #define VERBOSE */ +/* #define NOCTSCHK */ + +#ifndef SDEV +#define SDEV "/dev/cuaa0" +#endif + +#ifndef UDEV +#define UDEV "/dev/uhid0" +#endif + +#ifndef S_VERS +#define S_VERS "0.40" +#endif + +int fd; + +int cdcnv(int buf[], char *mak, char *cod); +extern char *cverrstr[]; + +int init_sio(void) +{ +#ifndef NOCTSCHK + int tcnt = 0; +#endif + struct termios tios; + int md; + + if ((fd = open(SDEV, O_RDWR)) == -1) { + fprintf(stderr, "Cannot open %s.\n", SDEV); + return 255; + } + + 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); + + md = TIOCM_LE|TIOCM_DTR|TIOCM_RTS; + ioctl(fd, TIOCMBIS, &md); + + /* wait for CTS: 充電待ち */ +#ifndef NOCTSCHK + for(;;) { + ioctl(fd, TIOCMGET, &md); + if (md & TIOCM_CTS) + break; + if (tcnt == 0) { + fprintf(stderr, "Waiting...."); + } + if (tcnt++ >= 30) { + fprintf(stderr, "Device timeout.\n"); + close(fd); + return 1; + } + sleep(1); + } +#endif /* NOCTSCHK */ + + md = TIOCM_RTS; + ioctl(fd, TIOCMBIC, &md); + usleep(10000); /* 10ms */ + ioctl(fd, TIOCMBIS, &md); + usleep(50000); /* 50ms */ + + 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]; + + 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; + } + +#ifdef VERBOSE + printf("Initializing...."); +#endif + if (init_usb()) + /* if (init_sio()) */ + return 255; +#ifdef VERBOSE + 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"); +#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); +#ifdef VERBOSE + printf(" --- got %d chars.\n", read(fd, sbuf, 8)); +#else + read(fd, sbuf, 8); +#endif + } + } + + /* charge(); */ + close(fd); + return 0; +}