transfermii-0.6.1/0000755000175200017540000000000010763523555013410 5ustar shinboshinbotransfermii-0.6.1/ChangeLog0000644000175200017540000000227610763523551015165 0ustar shinboshinbo2008-03-05 Arnaud Ysmal - Fixed a bug in the GUI - Fixed some errors in tmii - Added detection of cwiid 2008-02-04 Arnaud Ysmal - Fixed CRC issues - Removed mii_t and blockmii_t types - Imported libcwiid (www.cwiid.org) code to avoid dependencies 2007-09-01 Arnaud Ysmal - Fixed Makefiles 2007-09-01 Marylene Ysmal - Patched GUI for inline license information (Romain Beauxis) 2007-07-27 Arnaud Ysmal - fixed some endianness 2007-07-26 Arnaud Ysmal - Factorized some code (getMii*Ascii and setMii*Ascii) 2007-07-24 Arnaud Ysmal - added mii_t and blockmii_t types - merged fix_gcc-4.2_build patch from debian (Romain Beauxis) 2007-07-11 Arnaud Ysmal - fixed some endianness problems in miifunctions.c 2007-05-23 Arnaud Ysmal - updated to work with the svn version 2007-04-23 Arnaud Ysmal - replaced libwiimote by libcwiid from the cwiid' svn repository 2007-03-24 Arnaud Ysmal - fixed mac address parsing function transfermii-0.6.1/CMakeLists.txt0000644000175200017540000000200610763437400016137 0ustar shinboshinboINCLUDE(UsePkgConfig) PKGCONFIG(gtk+-2.0 GTK2_INCLUDE_DIR GTK2_LINK_DIR GTK2_LINK_FLAGS GTK2_CFLAGS) PROJECT(TransferMii) SUBDIRS(tmii) FIND_LIBRARY(libcwiid NAMES cwiid PATH /usr/lib/ /usr/local/lib/) IF(NOT libcwiid) SUBDIRS(cwiid) # CLI ADD_EXECUTABLE(transfermii_cli transfermii_cli.c) TARGET_LINK_LIBRARIES(transfermii_cli tmii cwiid) # GUI SET(CMAKE_C_FLAGS "${GTK2_CFLAGS} -Wall -Werror -DCWIID_STATIC") ADD_EXECUTABLE(transfermii_gui gui/pageAbout.c gui/pageLocal.c gui/pageWiimote.c gui/transfermii_gui.c) TARGET_LINK_LIBRARIES(transfermii_gui tmii ${GTK2_LINK_FLAGS} ${GTK2_CFLAGS} cwiid) ELSE(NOT libcwiid) # CLI ADD_EXECUTABLE(transfermii_cli transfermii_cli.c) TARGET_LINK_LIBRARIES(transfermii_cli tmii ${libcwiid}) # GUI SET(CMAKE_C_FLAGS "${GTK2_CFLAGS} -Wall -Werror") ADD_EXECUTABLE(transfermii_gui gui/pageAbout.c gui/pageLocal.c gui/pageWiimote.c gui/transfermii_gui.c) TARGET_LINK_LIBRARIES(transfermii_gui tmii ${GTK2_LINK_FLAGS} ${GTK2_CFLAGS} ${libcwiid}) ENDIF(NOT libcwiid) transfermii-0.6.1/cwiid/0000755000175200017540000000000010763522641014502 5ustar shinboshinbotransfermii-0.6.1/cwiid/bluetooth.c0000644000175200017540000001246510751650020016651 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-04-24 L. Donnie Smith (cwiid@abstrakraft.org> * * revised error messages * * 2007-04-12 L. Donnie Smith * * streamlined wiimote filter * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-07 L. Donnie Smith * * changed cwiid_info.class to btclass * * 2007-04-03 L. Donnie Smith * * fixed cwiid_find_wiimote seg fault * * 2007-04-02 L. Donnie Smith * * exception handling bugs * * 2007-04-01 L. Donnie Smith * * created file */ #include #include #include #include #include #include "cwiid_internal.h" /* When filtering wiimotes, in order to avoid having to store the * remote names before the blue_dev array is malloced (because we don't * yet know how many wiimotes there are, we'll assume there are no more * than dev_count, and realloc to the actual number afterwards, since * reallocing to a smaller chunk should be fast. */ #define BT_MAX_INQUIRY 256 /* timeout in 2 second units */ int cwiid_get_bdinfo_array(int dev_id, unsigned int timeout, int max_bdinfo, struct cwiid_bdinfo **bdinfo, uint8_t flags) { inquiry_info *dev_list = NULL; int max_inquiry; int dev_count; int sock = -1; int bdinfo_count; int i, j; int err = 0; int ret; /* NULLify for the benefit of error handling */ *bdinfo = NULL; /* If not given (=-1), get the first available Bluetooth interface */ if (dev_id == -1) { if ((dev_id = hci_get_route(NULL)) == -1) { cwiid_err(NULL, "No Bluetooth interface found"); return -1; } } /* Get Bluetooth Device List */ if ((flags & BT_NO_WIIMOTE_FILTER) && (max_bdinfo != -1)) { max_inquiry = max_bdinfo; } else { max_inquiry = BT_MAX_INQUIRY; } if ((dev_count = hci_inquiry(dev_id, timeout, max_inquiry, NULL, &dev_list, IREQ_CACHE_FLUSH)) == -1) { cwiid_err(NULL, "Bluetooth device inquiry error"); err = 1; goto CODA; } if (dev_count == 0) { bdinfo_count = 0; goto CODA; } /* Open connection to Bluetooth Interface */ if ((sock = hci_open_dev(dev_id)) == -1) { cwiid_err(NULL, "Bluetooth interface open error"); err = 1; goto CODA; } /* Allocate info list */ if (max_bdinfo == -1) { max_bdinfo = dev_count; } if ((*bdinfo = malloc(max_bdinfo * sizeof **bdinfo)) == NULL) { cwiid_err(NULL, "Memory allocation error (bdinfo array)"); err = 1; goto CODA; } /* Copy dev_list to bdinfo */ for (bdinfo_count=i=0; (i < dev_count) && (bdinfo_count < max_bdinfo); i++) { /* Filter by class */ if (!(flags & BT_NO_WIIMOTE_FILTER) && ((dev_list[i].dev_class[0] != WIIMOTE_CLASS_0) || (dev_list[i].dev_class[1] != WIIMOTE_CLASS_1) || (dev_list[i].dev_class[2] != WIIMOTE_CLASS_2))) { continue; } /* timeout (10000) in milliseconds */ if (hci_remote_name(sock, &dev_list[i].bdaddr, BT_NAME_LEN, (*bdinfo)[bdinfo_count].name, 10000)) { cwiid_err(NULL, "Bluetooth name read error"); err = 1; goto CODA; } /* Filter by name */ if (!(flags & BT_NO_WIIMOTE_FILTER) && strncmp((*bdinfo)[bdinfo_count].name, WIIMOTE_NAME, BT_NAME_LEN)) { continue; } /* Passed filter, add to bdinfo */ bacpy(&(*bdinfo)[bdinfo_count].bdaddr, &dev_list[i].bdaddr); for (j=0; j<3; j++) { (*bdinfo)[bdinfo_count].btclass[j] = dev_list[i].dev_class[j]; } bdinfo_count++; } if (bdinfo_count == 0) { free(*bdinfo); } else if (bdinfo_count < max_bdinfo) { if ((*bdinfo = realloc(*bdinfo, bdinfo_count * sizeof **bdinfo)) == NULL) { cwiid_err(NULL, "Memory reallocation error (bdinfo array)"); err = 1; goto CODA; } } CODA: if (dev_list) free(dev_list); if (sock != -1) hci_close_dev(sock); if (err) { if (*bdinfo) free(*bdinfo); ret = -1; } else { ret = bdinfo_count; } return ret; } int cwiid_find_wiimote(bdaddr_t *bdaddr, int timeout) { struct cwiid_bdinfo *bdinfo; int bdinfo_count; if (timeout == -1) { while ((bdinfo_count = cwiid_get_bdinfo_array(-1, 2, 1, &bdinfo, 0)) == 0); if (bdinfo_count == -1) { return -1; } } else { bdinfo_count = cwiid_get_bdinfo_array(-1, timeout, 1, &bdinfo, 0); if (bdinfo_count == -1) { return -1; } else if (bdinfo_count == 0) { cwiid_err(NULL, "No wiimotes found"); return -1; } } bacpy(bdaddr, &bdinfo[0].bdaddr); free(bdinfo); return 0; } transfermii-0.6.1/cwiid/CMakeLists.txt0000644000175200017540000000023210751645145017241 0ustar shinboshinboADD_LIBRARY(cwiid bluetooth.c command.c connect.c interface.c process.c state.c thread.c util.c) TARGET_LINK_LIBRARIES(cwiid bluetooth pthread rt) transfermii-0.6.1/cwiid/command.c0000644000175200017540000002246010751650020016256 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-05-16 L. Donnie Smith * * added cwiid_request_status, cwiid_set_let, cwiid_set_rumble, * cwiid_set_rpt_mode * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul * * added rw and beep functions from rw.c * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-04 L. Donnie Smith * * updated cwiid_read and cwiid_write to trigger and detect rw_error * * 2007-03-14 L. Donnie Smith * * audited error checking (coda and error handler sections) * * updated comments * * cwiid_read - changed to obey decode flag only for register read * * 2007-03-06 L. Donnie Smith * * added wiimote parameter to cwiid_err calls * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog * * type audit (stdint, const, char booleans) */ #include #include #include #include #include "cwiid_internal.h" int cwiid_command(struct wiimote *wiimote, enum cwiid_command command, int flags) { int ret; switch (command) { case CWIID_CMD_STATUS: ret = cwiid_request_status(wiimote); break; case CWIID_CMD_LED: ret = cwiid_set_led(wiimote, flags); break; case CWIID_CMD_RUMBLE: ret = cwiid_set_rumble(wiimote, flags); break; case CWIID_CMD_RPT_MODE: ret = cwiid_set_rpt_mode(wiimote, flags); break; default: ret = -1; break; } return ret; } int cwiid_request_status(cwiid_wiimote_t *wiimote) { unsigned char data; data = 0; if (send_report(wiimote, 0, RPT_STATUS_REQ, 1, &data)) { cwiid_err(wiimote, "Status request error"); return -1; } return 0; } int cwiid_set_led(cwiid_wiimote_t *wiimote, uint8_t led) { unsigned char data; /* TODO: assumption: char assignments are atomic, no mutex lock needed */ wiimote->state.led = led & 0x0F; data = wiimote->state.led << 4; if (send_report(wiimote, 0, RPT_LED_RUMBLE, 1, &data)) { cwiid_err(wiimote, "Report send error (led)"); return -1; } return 0; } int cwiid_set_rumble(cwiid_wiimote_t *wiimote, uint8_t rumble) { unsigned char data; /* TODO: assumption: char assignments are atomic, no mutex lock needed */ wiimote->state.rumble = rumble ? 1 : 0; data = wiimote->state.led << 4; if (send_report(wiimote, 0, RPT_LED_RUMBLE, 1, &data)) { cwiid_err(wiimote, "Report send error (led)"); return -1; } return 0; } int cwiid_set_rpt_mode(cwiid_wiimote_t *wiimote, uint8_t rpt_mode) { return update_rpt_mode(wiimote, rpt_mode); } #define RPT_READ_REQ_LEN 6 int cwiid_read(struct wiimote *wiimote, uint8_t flags, uint32_t offset, uint16_t len, void *data) { unsigned char buf[RPT_READ_REQ_LEN]; struct rw_mesg mesg; unsigned char *cursor; int ret = 0; int i; /* Compose read request packet */ buf[0]=flags & (CWIID_RW_EEPROM | CWIID_RW_REG); buf[1]=(unsigned char)((offset>>16) & 0xFF); buf[2]=(unsigned char)((offset>>8) & 0xFF); buf[3]=(unsigned char)(offset & 0xFF); buf[4]=(unsigned char)((len>>8) & 0xFF); buf[5]=(unsigned char)(len & 0xFF); /* Lock wiimote rw access */ if (pthread_mutex_lock(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex lock error (rw_mutex)"); return -1; } /* Setup read info */ wiimote->rw_status = RW_READ; /* TODO: Document: user is responsible for ensuring that read/write * operations are not in flight while disconnecting. Nothing serious, * just accesses to freed memory */ /* Send read request packet */ if (send_report(wiimote, 0, RPT_READ_REQ, RPT_READ_REQ_LEN, buf)) { cwiid_err(wiimote, "Report send error (read)"); ret = -1; goto CODA; } /* TODO:Better sanity checks (offset) */ /* Read packets */ for (cursor = data; cursor - (unsigned char *)data < len; cursor += mesg.len) { if (full_read(wiimote->rw_pipe[0], &mesg, sizeof mesg)) { cwiid_err(wiimote, "Pipe read error (rw pipe)"); ret = -1; goto CODA; } if (mesg.type == RW_CANCEL) { ret = -1; goto CODA; } else if (mesg.type != RW_READ) { cwiid_err(wiimote, "Unexpected write message"); ret = -1; goto CODA; } if (mesg.error) { cwiid_err(wiimote, "Wiimote read error"); ret = -1; goto CODA; } memcpy(cursor, &mesg.data, mesg.len); } CODA: /* Clear rw_status */ wiimote->rw_status = RW_IDLE; /* Unlock rw_mutex */ if (pthread_mutex_unlock(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex unlock error (rw_mutex) - deadlock warning"); } /* Decode (only for register reads) */ if ((ret == 0) && (flags & CWIID_RW_DECODE) && (flags & CWIID_RW_REG)) { for (i=0; i < len; i++) { ((unsigned char *)data)[i] = DECODE(((unsigned char *)data)[i]); } } return ret; } #define RPT_WRITE_LEN 21 int cwiid_write(struct wiimote *wiimote, uint8_t flags, uint32_t offset, uint16_t len, const void *data) { unsigned char buf[RPT_WRITE_LEN]; uint16_t sent=0; struct rw_mesg mesg; int ret = 0; /* Compose write packet header */ buf[0]=flags; /* Lock wiimote rw access */ if (pthread_mutex_lock(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex lock error (rw mutex)"); return -1; } /* Send packets */ wiimote->rw_status = RW_WRITE; while (sent>16) & 0xFF); buf[2]=(unsigned char)(((offset+sent)>>8) & 0xFF); buf[3]=(unsigned char)((offset+sent) & 0xFF); if (len-sent >= 0x10) { buf[4]=(unsigned char)0x10; } else { buf[4]=(unsigned char)(len-sent); } memcpy(buf+5, data+sent, buf[4]); if (send_report(wiimote, 0, RPT_WRITE, RPT_WRITE_LEN, buf)) { cwiid_err(wiimote, "Report send error (write)"); ret = -1; goto CODA; } /* Read packets from pipe */ if (read(wiimote->rw_pipe[0], &mesg, sizeof mesg) != sizeof mesg) { cwiid_err(wiimote, "Pipe read error (rw pipe)"); ret = -1; goto CODA; } if (mesg.type == RW_CANCEL) { ret = -1; goto CODA; } else if (mesg.type != RW_WRITE) { cwiid_err(wiimote, "Unexpected read message"); ret = -1; goto CODA; } if (mesg.error) { cwiid_err(wiimote, "Wiimote write error"); ret = -1; goto CODA; }; sent+=buf[4]; } CODA: /* Clear rw_status */ wiimote->rw_status = RW_IDLE; /* Unlock rw_mutex */ if (pthread_mutex_unlock(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex unlock error (rw_mutex) - deadlock warning"); } return ret; } struct write_seq speaker_enable_seq[] = { {WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x04", 1, 0}, {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0}, {WRITE_SEQ_MEM, 0xA20009, (const void *)"\x01", 1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xA20001, (const void *)"\x08", 1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xA20001, (const void *)"\x00\x00\x00\x0C\x40\x00\x00", 7, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xA20008, (const void *)"\x01", 1, CWIID_RW_REG}, {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x00", 1, 0} }; struct write_seq speaker_disable_seq[] = { {WRITE_SEQ_RPT, RPT_SPEAKER_MUTE, (const void *)"\x04", 1, 0}, {WRITE_SEQ_RPT, RPT_SPEAKER_ENABLE, (const void *)"\x00", 1, 0} }; #define SOUND_BUF_LEN 21 int cwiid_beep(cwiid_wiimote_t *wiimote) { /* unsigned char buf[SOUND_BUF_LEN] = { 0xA0, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33, 0xCC, 0x33}; */ unsigned char buf[SOUND_BUF_LEN] = { 0xA0, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3}; int i; int ret = 0; pthread_mutex_t timer_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t timer_cond = PTHREAD_COND_INITIALIZER; struct timespec t; if (exec_write_seq(wiimote, SEQ_LEN(speaker_enable_seq), speaker_enable_seq)) { cwiid_err(wiimote, "Speaker enable error"); ret = -1; } pthread_mutex_lock(&timer_mutex); for (i=0; i<100; i++) { clock_gettime(CLOCK_REALTIME, &t); t.tv_nsec += 10204081; /* t.tv_nsec += 7000000; */ if (send_report(wiimote, 0, RPT_SPEAKER_DATA, SOUND_BUF_LEN, buf)) { printf("%d\n", i); cwiid_err(wiimote, "Report send error (speaker data)"); ret = -1; break; } /* TODO: I should be shot for this, but hey, it works. * longterm - find a better wait */ pthread_cond_timedwait(&timer_cond, &timer_mutex, &t); } pthread_mutex_unlock(&timer_mutex); if (exec_write_seq(wiimote, SEQ_LEN(speaker_disable_seq), speaker_disable_seq)) { cwiid_err(wiimote, "Speaker disable error"); ret = -1; } return ret; } transfermii-0.6.1/cwiid/connect.c0000644000175200017540000002446110751650020016274 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-06-14 L. Donnie Smith * * added sleep after cwiid_find_wiimote call * * 2007-05-16 L. Donnie Smith * * remove error_pipe init and destruct * * renamed connect and disconnect to open and close * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-04 L. Donnie Smith * * cancel rw operations from cwiid_disconnect * * 2007-04-01 L. Donnie Smith * * cwiid_connect now takes a pointer to bdaddr_t * * changed cwiid_findfirst to cwiid_find_wiimote * * 2007-03-14 L. Donnie Smith * * changed memcpy to bacmp * * audited error checking (coda and error handler sections) * * updated comments * * 2007-03-06 L. Donnie Smith * * added wiimote parameter to cwiid_err calls * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog */ #include #include #include #include #include #include #include #include #include #include "cwiid_internal.h" pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; static int wiimote_id = 0; cwiid_wiimote_t *cwiid_open(bdaddr_t *bdaddr, int flags) { struct wiimote *wiimote = NULL; struct sockaddr_l2 remote_addr; char mesg_pipe_init = 0, status_pipe_init = 0, rw_pipe_init = 0, state_mutex_init = 0, rw_mutex_init = 0, rpt_mutex_init = 0, router_thread_init = 0, status_thread_init = 0; void *pthread_ret; /* Allocate wiimote */ if ((wiimote = malloc(sizeof *wiimote)) == NULL) { cwiid_err(NULL, "Memory allocation error (cwiid_wiimote_t)"); goto ERR_HND; } /* set flags */ wiimote->flags = flags; /* For error detection */ wiimote->ctl_socket = wiimote->int_socket = -1; /* Global Lock, Store and Increment wiimote_id */ if (pthread_mutex_lock(&global_mutex)) { cwiid_err(NULL, "Mutex lock error (global mutex)"); goto ERR_HND; } wiimote->id = wiimote_id++; if (pthread_mutex_unlock(&global_mutex)) { cwiid_err(wiimote, "Mutex unlock error (global mutex) - " "deadlock warning"); goto ERR_HND; } /* If BDADDR_ANY is given, find available wiimote */ if (bacmp(bdaddr, BDADDR_ANY) == 0) { if (cwiid_find_wiimote(bdaddr, 5)) { goto ERR_HND; } sleep(1); } /* Connect to Wiimote */ /* Control Channel */ memset(&remote_addr, 0, sizeof remote_addr); remote_addr.l2_family = AF_BLUETOOTH; remote_addr.l2_bdaddr = *bdaddr; remote_addr.l2_psm = htobs(CTL_PSM); if ((wiimote->ctl_socket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) { cwiid_err(wiimote, "Socket creation error (control socket)"); goto ERR_HND; } if (connect(wiimote->ctl_socket, (struct sockaddr *)&remote_addr, sizeof remote_addr)) { cwiid_err(wiimote, "Socket connect error (control channel)"); goto ERR_HND; } /* Interrupt Channel */ remote_addr.l2_psm = htobs(INT_PSM); if ((wiimote->int_socket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1) { cwiid_err(wiimote, "Socket creation error (interrupt socket)"); goto ERR_HND; } if (connect(wiimote->int_socket, (struct sockaddr *)&remote_addr, sizeof remote_addr)) { cwiid_err(wiimote, "Socket connect error (interrupt channel)"); goto ERR_HND; } /* Create pipes */ if (pipe(wiimote->mesg_pipe)) { cwiid_err(wiimote, "Pipe creation error (mesg pipe)"); goto ERR_HND; } mesg_pipe_init = 1; if (pipe(wiimote->status_pipe)) { cwiid_err(wiimote, "Pipe creation error (status pipe)"); goto ERR_HND; } status_pipe_init = 1; if (pipe(wiimote->rw_pipe)) { cwiid_err(wiimote, "Pipe creation error (rw pipe)"); goto ERR_HND; } rw_pipe_init = 1; /* Setup blocking */ if (fcntl(wiimote->mesg_pipe[1], F_SETFL, O_NONBLOCK)) { cwiid_err(wiimote, "File control error (mesg write pipe)"); goto ERR_HND; } if (wiimote->flags & CWIID_FLAG_NONBLOCK) { if (fcntl(wiimote->mesg_pipe[0], F_SETFL, O_NONBLOCK)) { cwiid_err(wiimote, "File control error (mesg read pipe)"); goto ERR_HND; } } /* Init mutexes */ if (pthread_mutex_init(&wiimote->state_mutex, NULL)) { cwiid_err(wiimote, "Mutex initialization error (state mutex)"); goto ERR_HND; } state_mutex_init = 1; if (pthread_mutex_init(&wiimote->rw_mutex, NULL)) { cwiid_err(wiimote, "Mutex initialization error (rw mutex)"); goto ERR_HND; } rw_mutex_init = 1; if (pthread_mutex_init(&wiimote->rpt_mutex, NULL)) { cwiid_err(wiimote, "Mutex initialization error (rpt mutex)"); goto ERR_HND; } rpt_mutex_init = 1; /* Set rw_status before starting router thread */ wiimote->rw_status = RW_IDLE; /* Launch interrupt channel listener and dispatch threads */ if (pthread_create(&wiimote->router_thread, NULL, (void *(*)(void *))&router_thread, wiimote)) { cwiid_err(wiimote, "Thread creation error (router thread)"); goto ERR_HND; } router_thread_init = 1; if (pthread_create(&wiimote->status_thread, NULL, (void *(*)(void *))&status_thread, wiimote)) { cwiid_err(wiimote, "Thread creation error (status thread)"); goto ERR_HND; } status_thread_init = 1; /* Success! Update state */ memset(&wiimote->state, 0, sizeof wiimote->state); wiimote->mesg_callback = NULL; cwiid_set_led(wiimote, 0); cwiid_request_status(wiimote); return wiimote; ERR_HND: if (wiimote) { /* Close threads */ if (router_thread_init) { pthread_cancel(wiimote->router_thread); if (pthread_join(wiimote->router_thread, &pthread_ret)) { cwiid_err(wiimote, "Thread join error (router thread)"); } else if (!((pthread_ret == PTHREAD_CANCELED) && (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from router thread"); } } if (status_thread_init) { pthread_cancel(wiimote->status_thread); if (pthread_join(wiimote->status_thread, &pthread_ret)) { cwiid_err(wiimote, "Thread join error (status thread)"); } else if (!((pthread_ret == PTHREAD_CANCELED) && (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from status thread"); } } /* Close Sockets */ if (wiimote->int_socket != -1) { if (close(wiimote->int_socket)) { cwiid_err(wiimote, "Socket close error (interrupt channel)"); } } if (wiimote->ctl_socket != -1) { if (close(wiimote->ctl_socket)) { cwiid_err(wiimote, "Socket close error (control channel)"); } } /* Close Pipes */ if (mesg_pipe_init) { if (close(wiimote->mesg_pipe[0]) || close(wiimote->mesg_pipe[1])) { cwiid_err(wiimote, "Pipe close error (mesg pipe)"); } } if (status_pipe_init) { if (close(wiimote->status_pipe[0]) || close(wiimote->status_pipe[1])) { cwiid_err(wiimote, "Pipe close error (status pipe)"); } } if (rw_pipe_init) { if (close(wiimote->rw_pipe[0]) || close(wiimote->rw_pipe[1])) { cwiid_err(wiimote, "Pipe close error (rw pipe)"); } } /* Destroy Mutexes */ if (state_mutex_init) { if (pthread_mutex_destroy(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex destroy error (state mutex)"); } } if (rw_mutex_init) { if (pthread_mutex_destroy(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex destroy error (rw mutex)"); } } if (rpt_mutex_init) { if (pthread_mutex_destroy(&wiimote->rpt_mutex)) { cwiid_err(wiimote, "Mutex destroy error (rpt mutex)"); } } free(wiimote); } return NULL; } int cwiid_close(struct wiimote *wiimote) { void *pthread_ret; /* Cancel and join router_thread and status_thread */ if (pthread_cancel(wiimote->router_thread)) { /* if thread quit abnormally, would have printed it's own error */ } if (pthread_join(wiimote->router_thread, &pthread_ret)) { cwiid_err(wiimote, "Thread join error (router thread)"); } else if (!((pthread_ret == PTHREAD_CANCELED) || (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from router thread"); } if (pthread_cancel(wiimote->status_thread)) { /* if thread quit abnormally, would have printed it's own error */ } if (pthread_join(wiimote->status_thread, &pthread_ret)) { cwiid_err(wiimote, "Thread join error (status thread)"); } else if (!((pthread_ret == PTHREAD_CANCELED) || (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from status thread"); } if (wiimote->mesg_callback) { if (cancel_mesg_callback(wiimote)) { /* prints it's own errors */ } } if (cancel_rw(wiimote)) { /* prints it's own errors */ } /* Close sockets */ if (close(wiimote->int_socket)) { cwiid_err(wiimote, "Socket close error (interrupt channel)"); } if (close(wiimote->ctl_socket)) { cwiid_err(wiimote, "Socket close error (control channel)"); } /* Close Pipes */ if (close(wiimote->mesg_pipe[0]) || close(wiimote->mesg_pipe[1])) { cwiid_err(wiimote, "Pipe close error (mesg pipe)"); } if (close(wiimote->status_pipe[0]) || close(wiimote->status_pipe[1])) { cwiid_err(wiimote, "Pipe close error (status pipe)"); } if (close(wiimote->rw_pipe[0]) || close(wiimote->rw_pipe[1])) { cwiid_err(wiimote, "Pipe close error (rw pipe)"); } /* Destroy mutexes */ if (pthread_mutex_destroy(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex destroy error (state)"); } if (pthread_mutex_destroy(&wiimote->rw_mutex)) { cwiid_err(wiimote, "Mutex destroy error (rw)"); } if (pthread_mutex_destroy(&wiimote->rpt_mutex)) { cwiid_err(wiimote, "Mutex destroy error (rpt)"); } free(wiimote); return 0; } transfermii-0.6.1/cwiid/cwiid.h0000644000175200017540000002177010751650025015754 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2008-08-14 L. Donnie Smith * * make cwiid_err_default public * * 2007-05-16 L. Donnie Smith * * changed cwiid_connect, cwiid_disconnect to cwiid_open, cwiid_close * * added cwiid_request_status, cwiid_set_let, cwiid_set_rumble, * cwiid_set_rpt_mode * * 2007-05-14 L. Donnie Smith * * added timestamp to message functions * * added cwiid_get_acc_cal * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-07 L. Donnie Smith * * changed cwiid_info.class to btclass * * 2007-04-04 L. Donnie Smith * * added cwiid_mesg_error message type * * 2007-04-01 L. Donnie Smith * * cwiid_connect now takes a pointer to bdaddr_t * * added cwiid_info definition and macros * * added cwiid_get_info_array prototype * * changed cwiid_findfirst to cwiid_find_wiimote * * 2007-03-05 L. Donnie Smith * * added cwiid_err_t definition * * added cwiid_set_err prototype * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog * * type audit (stdint, const, char booleans) */ #ifndef CWIID_H #define CWIID_H #include #include #include #include /* bdaddr_t */ /* Flags */ #define CWIID_FLAG_MESG_IFC 0x01 #define CWIID_FLAG_CONTINUOUS 0x02 #define CWIID_FLAG_REPEAT_BTN 0x04 #define CWIID_FLAG_NONBLOCK 0x08 /* Report Mode Flags */ #define CWIID_RPT_STATUS 0x01 #define CWIID_RPT_BTN 0x02 #define CWIID_RPT_ACC 0x04 #define CWIID_RPT_IR 0x08 #define CWIID_RPT_NUNCHUK 0x10 #define CWIID_RPT_CLASSIC 0x20 #define CWIID_RPT_EXT (CWIID_RPT_NUNCHUK | CWIID_RPT_CLASSIC) /* LED flags */ #define CWIID_LED1_ON 0x01 #define CWIID_LED2_ON 0x02 #define CWIID_LED3_ON 0x04 #define CWIID_LED4_ON 0x08 /* Button flags */ #define CWIID_BTN_2 0x0001 #define CWIID_BTN_1 0x0002 #define CWIID_BTN_B 0x0004 #define CWIID_BTN_A 0x0008 #define CWIID_BTN_MINUS 0x0010 #define CWIID_BTN_HOME 0x0080 #define CWIID_BTN_LEFT 0x0100 #define CWIID_BTN_RIGHT 0x0200 #define CWIID_BTN_DOWN 0x0400 #define CWIID_BTN_UP 0x0800 #define CWIID_BTN_PLUS 0x1000 #define CWIID_NUNCHUK_BTN_Z 0x01 #define CWIID_NUNCHUK_BTN_C 0x02 #define CWIID_CLASSIC_BTN_UP 0x0001 #define CWIID_CLASSIC_BTN_LEFT 0x0002 #define CWIID_CLASSIC_BTN_ZR 0x0004 #define CWIID_CLASSIC_BTN_X 0x0008 #define CWIID_CLASSIC_BTN_A 0x0010 #define CWIID_CLASSIC_BTN_Y 0x0020 #define CWIID_CLASSIC_BTN_B 0x0040 #define CWIID_CLASSIC_BTN_ZL 0x0080 #define CWIID_CLASSIC_BTN_R 0x0200 #define CWIID_CLASSIC_BTN_PLUS 0x0400 #define CWIID_CLASSIC_BTN_HOME 0x0800 #define CWIID_CLASSIC_BTN_MINUS 0x1000 #define CWIID_CLASSIC_BTN_L 0x2000 #define CWIID_CLASSIC_BTN_DOWN 0x4000 #define CWIID_CLASSIC_BTN_RIGHT 0x8000 /* Data Read/Write flags */ #define CWIID_RW_EEPROM 0x00 #define CWIID_RW_REG 0x04 #define CWIID_RW_DECODE 0x01 /* Maximum Data Read Length */ #define CWIID_MAX_READ_LEN 0xFFFF /* Array Index Defs */ #define CWIID_X 0 #define CWIID_Y 1 #define CWIID_Z 2 /* Acc Defs */ #define CWIID_ACC_MAX 0xFF /* IR Defs */ #define CWIID_IR_SRC_COUNT 4 #define CWIID_IR_X_MAX 1024 #define CWIID_IR_Y_MAX 768 /* Battery */ #define CWIID_BATTERY_MAX 0xD0 /* Classic Controller Maxes */ #define CWIID_CLASSIC_L_STICK_MAX 0x3F #define CWIID_CLASSIC_R_STICK_MAX 0x1F #define CWIID_CLASSIC_LR_MAX 0x1F /* Environment Variables */ #define WIIMOTE_BDADDR "WIIMOTE_BDADDR" /* Callback Maximum Message Count */ #define CWIID_MAX_MESG_COUNT 5 /* Enumerations */ enum cwiid_command { CWIID_CMD_STATUS, CWIID_CMD_LED, CWIID_CMD_RUMBLE, CWIID_CMD_RPT_MODE }; enum cwiid_mesg_type { CWIID_MESG_STATUS, CWIID_MESG_BTN, CWIID_MESG_ACC, CWIID_MESG_IR, CWIID_MESG_NUNCHUK, CWIID_MESG_CLASSIC, CWIID_MESG_ERROR, CWIID_MESG_UNKNOWN }; enum cwiid_ext_type { CWIID_EXT_NONE, CWIID_EXT_NUNCHUK, CWIID_EXT_CLASSIC, CWIID_EXT_UNKNOWN }; enum cwiid_error { CWIID_ERROR_NONE, CWIID_ERROR_DISCONNECT, CWIID_ERROR_COMM }; struct acc_cal { uint8_t zero[3]; uint8_t one[3]; }; /* Message Structs */ struct cwiid_status_mesg { enum cwiid_mesg_type type; uint8_t battery; enum cwiid_ext_type ext_type; }; struct cwiid_btn_mesg { enum cwiid_mesg_type type; uint16_t buttons; }; struct cwiid_acc_mesg { enum cwiid_mesg_type type; uint8_t acc[3]; }; struct cwiid_ir_src { char valid; uint16_t pos[2]; int8_t size; }; struct cwiid_ir_mesg { enum cwiid_mesg_type type; struct cwiid_ir_src src[CWIID_IR_SRC_COUNT]; }; struct cwiid_nunchuk_mesg { enum cwiid_mesg_type type; uint8_t stick[2]; uint8_t acc[3]; uint8_t buttons; }; struct cwiid_classic_mesg { enum cwiid_mesg_type type; uint8_t l_stick[2]; uint8_t r_stick[2]; uint8_t l; uint8_t r; uint16_t buttons; }; struct cwiid_error_mesg { enum cwiid_mesg_type type; enum cwiid_error error; }; union cwiid_mesg { enum cwiid_mesg_type type; struct cwiid_status_mesg status_mesg; struct cwiid_btn_mesg btn_mesg; struct cwiid_acc_mesg acc_mesg; struct cwiid_ir_mesg ir_mesg; struct cwiid_nunchuk_mesg nunchuk_mesg; struct cwiid_classic_mesg classic_mesg; struct cwiid_error_mesg error_mesg; }; /* State Structs */ struct nunchuk_state { uint8_t stick[2]; uint8_t acc[3]; uint8_t buttons; }; struct classic_state { uint8_t l_stick[2]; uint8_t r_stick[2]; uint8_t l; uint8_t r; uint16_t buttons; }; union ext_state { struct nunchuk_state nunchuk; struct classic_state classic; }; struct cwiid_state { uint8_t rpt_mode; uint8_t led; uint8_t rumble; uint8_t battery; uint16_t buttons; uint8_t acc[3]; struct cwiid_ir_src ir_src[CWIID_IR_SRC_COUNT]; enum cwiid_ext_type ext_type; union ext_state ext; enum cwiid_error error; }; /* Typedefs */ typedef struct wiimote cwiid_wiimote_t; typedef void cwiid_mesg_callback_t(cwiid_wiimote_t *, int, union cwiid_mesg [], struct timespec *); typedef void cwiid_err_t(cwiid_wiimote_t *, const char *, va_list ap); /* get_bdinfo */ #define BT_NO_WIIMOTE_FILTER 0x01 #define BT_NAME_LEN 32 struct cwiid_bdinfo { bdaddr_t bdaddr; uint8_t btclass[3]; char name[BT_NAME_LEN]; }; #ifdef __cplusplus extern "C" { #endif /* Error reporting (library wide) */ int cwiid_set_err(cwiid_err_t *err); void cwiid_err_default(struct wiimote *wiimote, const char *str, va_list ap); /* Connection */ #define cwiid_connect cwiid_open #define cwiid_disconnect cwiid_close cwiid_wiimote_t *cwiid_open(bdaddr_t *bdaddr, int flags); int cwiid_close(cwiid_wiimote_t *wiimote); int cwiid_get_id(cwiid_wiimote_t *wiimote); int cwiid_set_data(cwiid_wiimote_t *wiimote, const void *data); const void *cwiid_get_data(cwiid_wiimote_t *wiimote); int cwiid_enable(cwiid_wiimote_t *wiimote, int flags); int cwiid_disable(cwiid_wiimote_t *wiimote, int flags); /* Interfaces */ int cwiid_set_mesg_callback(cwiid_wiimote_t *wiimote, cwiid_mesg_callback_t *callback); int cwiid_get_mesg(cwiid_wiimote_t *wiimote, int *mesg_count, union cwiid_mesg *mesg[], struct timespec *timestamp); int cwiid_get_state(cwiid_wiimote_t *wiimote, struct cwiid_state *state); int cwiid_get_acc_cal(struct wiimote *wiimote, enum cwiid_ext_type ext_type, struct acc_cal *acc_cal); /* Operations */ int cwiid_command(cwiid_wiimote_t *wiimote, enum cwiid_command command, int flags); int cwiid_request_status(cwiid_wiimote_t *wiimote); int cwiid_set_led(cwiid_wiimote_t *wiimote, uint8_t led); int cwiid_set_rumble(cwiid_wiimote_t *wiimote, uint8_t rumble); int cwiid_set_rpt_mode(cwiid_wiimote_t *wiimote, uint8_t rpt_mode); int cwiid_read(cwiid_wiimote_t *wiimote, uint8_t flags, uint32_t offset, uint16_t len, void *data); int cwiid_write(cwiid_wiimote_t *wiimote, uint8_t flags, uint32_t offset, uint16_t len, const void *data); /* int cwiid_beep(cwiid_wiimote_t *wiimote); */ /* HCI functions */ int cwiid_get_bdinfo_array(int dev_id, unsigned int timeout, int max_bdinfo, struct cwiid_bdinfo **bdinfo, uint8_t flags); int cwiid_find_wiimote(bdaddr_t *bdaddr, int timeout); #ifdef __cplusplus } #endif #endif transfermii-0.6.1/cwiid/cwiid_internal.h0000644000175200017540000001516110751650025017645 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-05-16 L. Donnie Smith * * remove error_pipe * * add struct mesg_array to process_error * * 2007-05-14 L. Donnie Smith * * added timestamp to mesg_array * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-04 L. Donnie Smith * * moved RW error state to separate member * * 2007-04-01 L. Donnie Smith * * removed CWIID_CMP_LEN macro and cwiid_findfirst prototype * * 2007-03-05 L. Donnie Smith * * added wiimote parameter to cwiid_err prototype * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog * * type audit (stdint, const, char booleans) */ #ifndef CWIID_INTERNAL_H #define CWIID_INTERNAL_H #include #include #include /* ssize_t */ #include "cwiid.h" /* Bluetooth magic numbers */ #define BT_TRANS_MASK 0xF0 #define BT_TRANS_HANDSHAKE 0x00 #define BT_TRANS_SET_REPORT 0x50 #define BT_TRANS_DATA 0xA0 #define BT_TRANS_DATAC 0xB0 #define BT_PARAM_MASK 0x0F /* HANDSHAKE params */ #define BT_PARAM_SUCCESSFUL 0x00 #define BT_PARAM_NOT_READY 0x01 #define BT_PARAM_ERR_INVALID_REPORT_ID 0x02 #define BT_PARAM_ERR_UNSUPPORTED_REQUEST 0x03 #define BT_PARAM_ERR_INVALID_PARAMETER 0x04 #define BT_PARAM_ERR_UNKNOWN 0x0E #define BT_PARAM_ERR_FATAL 0x0F /* SET_REPORT, DATA, DATAC params */ #define BT_PARAM_INPUT 0x01 #define BT_PARAM_OUTPUT 0x02 #define BT_PARAM_FEATURE 0x03 /* Wiimote specific magic numbers */ #define WIIMOTE_NAME "Nintendo RVL-CNT-01" #define WIIMOTE_CLASS_0 0x04 #define WIIMOTE_CLASS_1 0x25 #define WIIMOTE_CLASS_2 0x00 /* Wiimote port/channel/PSMs */ #define CTL_PSM 17 #define INT_PSM 19 /* Report numbers */ #define RPT_LED_RUMBLE 0x11 #define RPT_RPT_MODE 0x12 #define RPT_IR_ENABLE1 0x13 #define RPT_SPEAKER_ENABLE 0x14 #define RPT_STATUS_REQ 0x15 #define RPT_WRITE 0x16 #define RPT_READ_REQ 0x17 #define RPT_SPEAKER_DATA 0x18 #define RPT_SPEAKER_MUTE 0x19 #define RPT_IR_ENABLE2 0x1A #define RPT_STATUS 0x20 #define RPT_READ_DATA 0x21 #define RPT_WRITE_ACK 0x22 #define RPT_BTN 0x30 #define RPT_BTN_ACC 0x31 #define RPT_BTN_EXT8 0x32 #define RPT_BTN_ACC_IR12 0x33 #define RPT_BTN_EXT19 0x34 #define RPT_BTN_ACC_EXT16 0x35 #define RPT_BTN_IR10_EXT9 0x36 #define RPT_BTN_ACC_IR10_EXT6 0x37 #define RPT_EXT21 0x3D #define RPT_BTN_ACC_IR36_1 0x3E #define RPT_BTN_ACC_IR36_2 0x3F /* Button Mask (masks unknown bits in button bytes) */ #define BTN_MASK_0 0x1F #define BTN_MASK_1 0x9F #define NUNCHUK_BTN_MASK 0x03 /* Extension Values */ #define EXT_NONE 0x2E #define EXT_PARTIAL 0xFF #define EXT_NUNCHUK 0x00 #define EXT_CLASSIC 0x01 /* IR Enable blocks */ #define MARCAN_IR_BLOCK_1 "\x00\x00\x00\x00\x00\x00\x90\x00\xC0" #define MARCAN_IR_BLOCK_2 "\x40\x00" #define CLIFF_IR_BLOCK_1 "\x02\x00\x00\x71\x01\x00\xAA\x00\x64" #define CLIFF_IR_BLOCK_2 "\x63\x03" /* Extension Decode */ #define DECODE(a) (((a ^ 0x17)+0x17)&0xFF) /* Write Sequences */ enum write_seq_type { WRITE_SEQ_RPT, WRITE_SEQ_MEM }; /* send_report flags */ #define SEND_RPT_NO_RUMBLE 0x01 struct write_seq { enum write_seq_type type; uint32_t report_offset; const void *data; uint16_t len; uint8_t flags; }; #define SEQ_LEN(seq) (sizeof(seq)/sizeof(struct write_seq)) /* Message arrays */ struct mesg_array { uint8_t count; struct timespec timestamp; union cwiid_mesg array[CWIID_MAX_MESG_COUNT]; }; /* RW State/Mesg */ enum rw_status { RW_IDLE, RW_READ, RW_WRITE, RW_CANCEL }; struct rw_mesg { enum rw_status type; uint8_t error; uint32_t offset; uint8_t len; char data[16]; }; /* Wiimote struct */ struct wiimote { int flags; int ctl_socket; int int_socket; pthread_t router_thread; pthread_t status_thread; pthread_t mesg_callback_thread; int mesg_pipe[2]; int status_pipe[2]; int rw_pipe[2]; struct cwiid_state state; enum rw_status rw_status; cwiid_mesg_callback_t *mesg_callback; pthread_mutex_t state_mutex; pthread_mutex_t rw_mutex; pthread_mutex_t rpt_mutex; int id; const void *data; }; /* prototypes */ /* thread.c */ void *router_thread(struct wiimote *wiimote); void *status_thread(struct wiimote *wiimote); void *mesg_callback_thread(struct wiimote *wiimote); /* util.c */ void cwiid_err(struct wiimote *wiimote, const char *str, ...); int verify_handshake(struct wiimote *wiimote); int send_report(struct wiimote *wiimote, uint8_t flags, uint8_t report, size_t len, const void *data); int exec_write_seq(struct wiimote *wiimote, unsigned int len, struct write_seq *seq); int full_read(int fd, void *buf, size_t len); int write_mesg_array(struct wiimote *wiimote, struct mesg_array *ma); int read_mesg_array(int fd, struct mesg_array *ma); int cancel_rw(struct wiimote *wiimote); int cancel_mesg_callback(struct wiimote *wiimote); /* process.c */ int process_error(struct wiimote *, ssize_t, struct mesg_array *); int process_status(struct wiimote *, const unsigned char *, struct mesg_array *); int process_btn(struct wiimote *, const unsigned char *, struct mesg_array *); int process_acc(struct wiimote *, const unsigned char *, struct mesg_array *); int process_ir10(struct wiimote *, const unsigned char *, struct mesg_array *); int process_ir12(struct wiimote *, const unsigned char *, struct mesg_array *); int process_ext(struct wiimote *, unsigned char *, unsigned char, struct mesg_array *); int process_read(struct wiimote *, unsigned char *); int process_write(struct wiimote *, unsigned char *); /* state.c */ int update_state(struct wiimote *wiimote, struct mesg_array *ma); int update_rpt_mode(struct wiimote *wiimote, int8_t rpt_mode); #endif transfermii-0.6.1/cwiid/interface.c0000644000175200017540000001061110751650020016573 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-05-14 L. Donnie Smith * * added timestamp to cwiid_get_mesg * * added cwiid_get_acc_cal * * 2007-04-24 L. Donnie Smith * * created for API overhaul */ #include #include #include #include #include #include #include "cwiid_internal.h" int cwiid_get_id(struct wiimote *wiimote) { return wiimote->id; } int cwiid_set_data(struct wiimote *wiimote, const void *data) { wiimote->data = data; return 0; } const void *cwiid_get_data(struct wiimote *wiimote) { return wiimote->data; } int cwiid_enable(struct wiimote *wiimote, int flags) { if ((flags & CWIID_FLAG_NONBLOCK) && !(wiimote->flags & CWIID_FLAG_NONBLOCK)) { if (fcntl(wiimote->mesg_pipe[0], F_SETFL, O_NONBLOCK)) { cwiid_err(wiimote, "File control error (mesg pipe)"); return -1; } } wiimote->flags |= flags; return 0; } int cwiid_disable(struct wiimote *wiimote, int flags) { if ((flags & CWIID_FLAG_NONBLOCK) && (wiimote->flags & CWIID_FLAG_NONBLOCK)) { if (fcntl(wiimote->mesg_pipe[0], F_SETFL, 0)) { cwiid_err(wiimote, "File control error (mesg pipe)"); return -1; } } wiimote->flags &= ~flags; return 0; } int cwiid_set_mesg_callback(struct wiimote *wiimote, cwiid_mesg_callback_t *callback) { if (wiimote->mesg_callback) { if (cancel_mesg_callback(wiimote)) { /* prints it's own errors */ return -1; } } wiimote->mesg_callback = callback; if (wiimote->mesg_callback) { if (pthread_create(&wiimote->mesg_callback_thread, NULL, (void *(*)(void *))&mesg_callback_thread, wiimote)) { cwiid_err(wiimote, "Thread creation error (callback thread)"); return -1; } } return 0; } int cwiid_get_mesg(struct wiimote *wiimote, int *mesg_count, union cwiid_mesg *mesg[], struct timespec *timestamp) { struct mesg_array ma; if (read_mesg_array(wiimote->mesg_pipe[0], &ma)) { if (errno == EAGAIN) { return -1; } else { cwiid_err(wiimote, "Pipe read error (mesg_pipe)"); return -1; } } *mesg_count = ma.count; *timestamp = ma.timestamp; if ((*mesg = malloc(ma.count * sizeof ma.array[0])) == NULL) { cwiid_err(wiimote, "Memory allocation error (mesg array)"); return -1; } memcpy(*mesg, &ma.array, ma.count * sizeof (*mesg)[0]); return 0; } int cwiid_get_state(struct wiimote *wiimote, struct cwiid_state *state) { if (pthread_mutex_lock(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex lock error (state mutex)"); return -1; } memcpy(state, &wiimote->state, sizeof *state); if (pthread_mutex_unlock(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex unlock error (state mutex) - " "deadlock warning"); return -1; } return 0; } int cwiid_get_acc_cal(struct wiimote *wiimote, enum cwiid_ext_type ext_type, struct acc_cal *acc_cal) { uint8_t flags; uint32_t offset; unsigned char buf[7]; char *err_str; switch (ext_type) { case CWIID_EXT_NONE: flags = CWIID_RW_EEPROM; offset = 0x16; err_str = ""; break; case CWIID_EXT_NUNCHUK: flags = CWIID_RW_REG | CWIID_RW_DECODE; offset = 0xA40020; err_str = "nunchuk "; break; default: cwiid_err(wiimote, "Unsupported calibration request"); return -1; } if (cwiid_read(wiimote, flags, offset, 7, buf)) { cwiid_err(wiimote, "Read error (%scal)", err_str); return -1; } acc_cal->zero[CWIID_X] = buf[0]; acc_cal->zero[CWIID_Y] = buf[1]; acc_cal->zero[CWIID_Z] = buf[2]; acc_cal->one[CWIID_X] = buf[4]; acc_cal->one[CWIID_Y] = buf[5]; acc_cal->one[CWIID_Z] = buf[6]; return 0; } transfermii-0.6.1/cwiid/Makefile.old0000644000175200017540000000063710763522617016730 0ustar shinboshinbo#Copyright (C) 2007-2008 Arnaud Ysmal CC=gcc CFLAGS=-Wall -Werror SRCS=bluetooth.c command.c connect.c interface.c process.c state.c thread.c \ util.c LIBNAME=libcwiid.a OBJS= $(SRCS:.c=.o) all : $(LIBNAME) $(LIBNAME) : $(OBJS) ar rc $(LIBNAME) $^ ranlib $(LIBNAME) %.o: %.c $(CC) -o $@ -c $< $(CFLAGS) .PHONY: clean mrproper clean: rm -rf $(OBJS) mrproper: clean rm -rf $(LIBNAME) transfermii-0.6.1/cwiid/process.c0000644000175200017540000001674610751650020016330 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-05-16 L. Donnie Smith * * process_err adds error_mesg to mesg_array * * 2007-04-24 L. Donnie Smith * * created for API overhaul (moved from old event.c) */ #include #include "cwiid_internal.h" int process_error(struct wiimote *wiimote, ssize_t len, struct mesg_array *ma) { struct cwiid_error_mesg *error_mesg; error_mesg = &ma->array[ma->count++].error_mesg; error_mesg->type = CWIID_MESG_ERROR; if (len == 0) { error_mesg->error = CWIID_ERROR_DISCONNECT; } else { error_mesg->error = CWIID_ERROR_COMM; } if (cancel_rw(wiimote)) { cwiid_err(wiimote, "RW cancel error"); } return 0; } int process_status(struct wiimote *wiimote, const unsigned char *data, struct mesg_array *ma) { struct cwiid_status_mesg status_mesg; status_mesg.type = CWIID_MESG_STATUS; status_mesg.battery = data[5]; if (data[2] & 0x02) { /* status_thread will figure out what it is */ status_mesg.ext_type = CWIID_EXT_UNKNOWN; } else { status_mesg.ext_type = CWIID_EXT_NONE; } if (write(wiimote->status_pipe[1], &status_mesg, sizeof status_mesg) != sizeof status_mesg) { cwiid_err(wiimote, "Status pipe write error"); return -1; } return 0; } int process_btn(struct wiimote *wiimote, const unsigned char *data, struct mesg_array *ma) { struct cwiid_btn_mesg *btn_mesg; uint16_t buttons; buttons = (data[0] & BTN_MASK_0)<<8 | (data[1] & BTN_MASK_1); if (wiimote->state.rpt_mode & CWIID_RPT_BTN) { if ((wiimote->state.buttons != buttons) || (wiimote->flags & CWIID_FLAG_REPEAT_BTN)) { btn_mesg = &ma->array[ma->count++].btn_mesg; btn_mesg->type = CWIID_MESG_BTN; btn_mesg->buttons = buttons; } } return 0; } int process_acc(struct wiimote *wiimote, const unsigned char *data, struct mesg_array *ma) { struct cwiid_acc_mesg *acc_mesg; if (wiimote->state.rpt_mode & CWIID_RPT_ACC) { acc_mesg = &ma->array[ma->count++].acc_mesg; acc_mesg->type = CWIID_MESG_ACC; acc_mesg->acc[CWIID_X] = data[0]; acc_mesg->acc[CWIID_Y] = data[1]; acc_mesg->acc[CWIID_Z] = data[2]; } return 0; } int process_ir10(struct wiimote *wiimote, const unsigned char *data, struct mesg_array *ma) { struct cwiid_ir_mesg *ir_mesg; int i; const unsigned char *block; if (wiimote->state.rpt_mode & CWIID_RPT_IR) { ir_mesg = &ma->array[ma->count++].ir_mesg; ir_mesg->type = CWIID_MESG_IR; for (i=0, block=data; i < CWIID_IR_SRC_COUNT; i+=2, block+=5) { if (block[0] == 0xFF) { ir_mesg->src[i].valid = 0; } else { ir_mesg->src[i].valid = 1; ir_mesg->src[i].pos[CWIID_X] = ((uint16_t)block[2] & 0x30)<<4 | (uint16_t)block[0]; ir_mesg->src[i].pos[CWIID_Y] = ((uint16_t)block[2] & 0xC0)<<2 | (uint16_t)block[1]; ir_mesg->src[i].size = -1; } if (block[3] == 0xFF) { ir_mesg->src[i+1].valid = 0; } else { ir_mesg->src[i+1].valid = 1; ir_mesg->src[i+1].pos[CWIID_X] = ((uint16_t)block[2] & 0x03)<<8 | (uint16_t)block[3]; ir_mesg->src[i+1].pos[CWIID_Y] = ((uint16_t)block[2] & 0x0C)<<6 | (uint16_t)block[4]; ir_mesg->src[i+1].size = -1; } } } return 0; } int process_ir12(struct wiimote *wiimote, const unsigned char *data, struct mesg_array *ma) { struct cwiid_ir_mesg *ir_mesg; int i; const unsigned char *block; if (wiimote->state.rpt_mode & CWIID_RPT_IR) { ir_mesg = &ma->array[ma->count++].ir_mesg; ir_mesg->type = CWIID_MESG_IR; for (i=0, block=data; i < CWIID_IR_SRC_COUNT; i++, block+=3) { if (block[0] == 0xFF) { ir_mesg->src[i].valid = 0; } else { ir_mesg->src[i].valid = 1; ir_mesg->src[i].pos[CWIID_X] = ((uint16_t)block[2] & 0x30)<<4 | (uint16_t)block[0]; ir_mesg->src[i].pos[CWIID_Y] = ((uint16_t)block[2] & 0xC0)<<2 | (uint16_t)block[1]; ir_mesg->src[i].size = block[2] & 0x0F; } } } return 0; } int process_ext(struct wiimote *wiimote, unsigned char *data, unsigned char len, struct mesg_array *ma) { struct cwiid_nunchuk_mesg *nunchuk_mesg; struct cwiid_classic_mesg *classic_mesg; int i; switch (wiimote->state.ext_type) { case CWIID_EXT_NONE: cwiid_err(wiimote, "Received unexpected extension report"); break; case CWIID_EXT_UNKNOWN: break; case CWIID_EXT_NUNCHUK: if (wiimote->state.rpt_mode & CWIID_RPT_NUNCHUK) { nunchuk_mesg = &ma->array[ma->count++].nunchuk_mesg; nunchuk_mesg->type = CWIID_MESG_NUNCHUK; nunchuk_mesg->stick[CWIID_X] = DECODE(data[0]); nunchuk_mesg->stick[CWIID_Y] = DECODE(data[1]); nunchuk_mesg->acc[CWIID_X] = DECODE(data[2]); nunchuk_mesg->acc[CWIID_Y] = DECODE(data[3]); nunchuk_mesg->acc[CWIID_Z] = DECODE(data[4]); nunchuk_mesg->buttons = ~DECODE(data[5]) & NUNCHUK_BTN_MASK; } break; case CWIID_EXT_CLASSIC: if (wiimote->state.rpt_mode & CWIID_RPT_CLASSIC) { classic_mesg = &ma->array[ma->count++].classic_mesg; classic_mesg->type = CWIID_MESG_CLASSIC; for (i=0; i < 6; i++) { data[i] = DECODE(data[i]); } classic_mesg->l_stick[CWIID_X] = data[0] & 0x3F; classic_mesg->l_stick[CWIID_Y] = data[1] & 0x3F; classic_mesg->r_stick[CWIID_X] = (data[0] & 0xC0)>>3 | (data[1] & 0xC0)>>5 | (data[2] & 0x80)>>7; classic_mesg->r_stick[CWIID_Y] = data[2] & 0x1F; classic_mesg->l = (data[2] & 0x60)>>2 | (data[3] & 0xE0)>>5; classic_mesg->r = data[3] & 0x1F; classic_mesg->buttons = ~((uint16_t)data[4]<<8 | (uint16_t)data[5]); } break; } return 0; } int process_read(struct wiimote *wiimote, unsigned char *data) { struct rw_mesg rw_mesg; if (wiimote->rw_status != RW_READ) { cwiid_err(wiimote, "Received unexpected read report"); return -1; } rw_mesg.type = RW_READ; rw_mesg.len = (data[0]>>4)+1; rw_mesg.error = data[0] & 0x0F; memcpy(&rw_mesg.data, data+3, rw_mesg.len); if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) != sizeof rw_mesg) { cwiid_err(wiimote, "RW pipe write error"); return -1; } return 0; } int process_write(struct wiimote *wiimote, unsigned char *data) { struct rw_mesg rw_mesg; if (wiimote->rw_status != RW_WRITE) { cwiid_err(wiimote, "Received unexpected write report"); return -1; } rw_mesg.type = RW_WRITE; rw_mesg.error = data[0]; if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) != sizeof rw_mesg) { cwiid_err(wiimote, "RW pipe write error"); return -1; } return 0; } transfermii-0.6.1/cwiid/state.c0000644000175200017540000001671610751650020015767 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-04-24 L. Donnie Smith * * created for API overhaul (update_rpt_mode moved from command.c) */ #include #include #include "cwiid_internal.h" int update_state(struct wiimote *wiimote, struct mesg_array *ma) { int i; union cwiid_mesg *mesg; if (pthread_mutex_lock(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex lock error (state mutex)"); return -1; } for (i=0; i < ma->count; i++) { mesg = &ma->array[i]; switch (mesg->type) { case CWIID_MESG_STATUS: wiimote->state.battery = mesg->status_mesg.battery; if (wiimote->state.ext_type != mesg->status_mesg.ext_type) { memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext); wiimote->state.ext_type = mesg->status_mesg.ext_type; } break; case CWIID_MESG_BTN: wiimote->state.buttons = mesg->btn_mesg.buttons; break; case CWIID_MESG_ACC: memcpy(wiimote->state.acc, mesg->acc_mesg.acc, sizeof wiimote->state.acc); break; case CWIID_MESG_IR: memcpy(wiimote->state.ir_src, mesg->ir_mesg.src, sizeof wiimote->state.ir_src); break; case CWIID_MESG_NUNCHUK: memcpy(wiimote->state.ext.nunchuk.stick, mesg->nunchuk_mesg.stick, sizeof wiimote->state.ext.nunchuk.stick); memcpy(wiimote->state.ext.nunchuk.acc, mesg->nunchuk_mesg.acc, sizeof wiimote->state.ext.nunchuk.acc); wiimote->state.ext.nunchuk.buttons = mesg->nunchuk_mesg.buttons; break; case CWIID_MESG_CLASSIC: memcpy(wiimote->state.ext.classic.l_stick, mesg->classic_mesg.l_stick, sizeof wiimote->state.ext.classic.l_stick); memcpy(wiimote->state.ext.classic.r_stick, mesg->classic_mesg.r_stick, sizeof wiimote->state.ext.classic.r_stick); wiimote->state.ext.classic.l = mesg->classic_mesg.l; wiimote->state.ext.classic.r = mesg->classic_mesg.r; wiimote->state.ext.classic.buttons = mesg->classic_mesg.buttons; break; case CWIID_MESG_ERROR: wiimote->state.error = mesg->error_mesg.error; break; case CWIID_MESG_UNKNOWN: /* do nothing, error has already been printed */ break; } } if (pthread_mutex_unlock(&wiimote->state_mutex)) { cwiid_err(wiimote, "Mutex unlock error (state mutex) - " "deadlock warning"); return -1; } return 0; } /* IR Sensitivity Block */ unsigned char ir_block1[] = CLIFF_IR_BLOCK_1; unsigned char ir_block2[] = CLIFF_IR_BLOCK_2; struct write_seq ir_enable10_seq[] = { {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0}, {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0}, {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x01", 1, CWIID_RW_REG} }; struct write_seq ir_enable12_seq[] = { {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x04", 1, 0}, {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x04", 1, 0}, {WRITE_SEQ_MEM, 0xB00030, (const void *)"\x08", 1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB00000, ir_block1, sizeof(ir_block1)-1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB0001A, ir_block2, sizeof(ir_block2)-1, CWIID_RW_REG}, {WRITE_SEQ_MEM, 0xB00033, (const void *)"\x03", 1, CWIID_RW_REG} }; struct write_seq ir_disable_seq[] = { {WRITE_SEQ_RPT, RPT_IR_ENABLE1, (const void *)"\x00", 1, 0}, {WRITE_SEQ_RPT, RPT_IR_ENABLE2, (const void *)"\x00", 1, 0} }; #define RPT_MODE_BUF_LEN 2 int update_rpt_mode(struct wiimote *wiimote, int8_t rpt_mode) { unsigned char buf[RPT_MODE_BUF_LEN]; uint8_t rpt_type; struct write_seq *ir_enable_seq; int seq_len; /* rpt_mode = bitmask of requested report types */ /* rpt_type = report id sent to the wiimote */ if (pthread_mutex_lock(&wiimote->rpt_mutex)) { cwiid_err(wiimote, "Mutex lock error (rpt mutex)"); return -1; } /* -1 updates the reporting mode using old rpt_mode * (reporting type may change if extensions are * plugged in/unplugged */ if (rpt_mode == -1) { rpt_mode = wiimote->state.rpt_mode; } /* Pick a report mode based on report flags */ if ((rpt_mode & CWIID_RPT_EXT) && ((wiimote->state.ext_type == CWIID_EXT_NUNCHUK) || (wiimote->state.ext_type == CWIID_EXT_CLASSIC))) { if ((rpt_mode & CWIID_RPT_IR) && (rpt_mode & CWIID_RPT_ACC)) { rpt_type = RPT_BTN_ACC_IR10_EXT6; ir_enable_seq = ir_enable10_seq; seq_len = SEQ_LEN(ir_enable10_seq); } else if (rpt_mode & CWIID_RPT_IR) { rpt_type = RPT_BTN_IR10_EXT9; ir_enable_seq = ir_enable10_seq; seq_len = SEQ_LEN(ir_enable10_seq); } else if (rpt_mode & CWIID_RPT_ACC) { rpt_type = RPT_BTN_ACC_EXT16; } else if (rpt_mode & CWIID_RPT_BTN) { rpt_type = RPT_BTN_EXT8; } else { rpt_type = RPT_EXT21; } } else { if (rpt_mode & CWIID_RPT_IR) { rpt_type = RPT_BTN_ACC_IR12; ir_enable_seq = ir_enable12_seq; seq_len = SEQ_LEN(ir_enable12_seq); } else if (rpt_mode & CWIID_RPT_ACC) { rpt_type = RPT_BTN_ACC; } else { rpt_type = RPT_BTN; } } /* Enable IR */ /* TODO: only do this when necessary (record old IR mode) */ if ((rpt_mode & CWIID_RPT_IR)) { if (exec_write_seq(wiimote, seq_len, ir_enable_seq)) { cwiid_err(wiimote, "IR enable error"); return -1; } } /* Disable IR */ else if ((wiimote->state.rpt_mode & CWIID_RPT_IR) && !(rpt_mode & CWIID_RPT_IR)) { if (exec_write_seq(wiimote, SEQ_LEN(ir_disable_seq), ir_disable_seq)) { cwiid_err(wiimote, "IR disable error"); return -1; } } /* Send SET_REPORT */ buf[0] = (wiimote->flags & CWIID_FLAG_CONTINUOUS) ? 0x04 : 0; buf[1] = rpt_type; if (send_report(wiimote, 0, RPT_RPT_MODE, RPT_MODE_BUF_LEN, buf)) { cwiid_err(wiimote, "Send report error (report mode)"); return -1; } /* clear state for unreported data */ if (CWIID_RPT_BTN & ~rpt_mode & wiimote->state.rpt_mode) { wiimote->state.buttons = 0; } if (CWIID_RPT_ACC & ~rpt_mode & wiimote->state.rpt_mode) { memset(wiimote->state.acc, 0, sizeof wiimote->state.acc); } if (CWIID_RPT_IR & ~rpt_mode & wiimote->state.rpt_mode) { memset(wiimote->state.ir_src, 0, sizeof wiimote->state.ir_src); } if ((wiimote->state.ext_type == CWIID_EXT_NUNCHUK) && (CWIID_RPT_NUNCHUK & ~rpt_mode & wiimote->state.rpt_mode)) { memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext); } else if ((wiimote->state.ext_type == CWIID_EXT_CLASSIC) && (CWIID_RPT_CLASSIC & ~rpt_mode & wiimote->state.rpt_mode)) { memset(&wiimote->state.ext, 0, sizeof wiimote->state.ext); } wiimote->state.rpt_mode = rpt_mode; if (pthread_mutex_unlock(&wiimote->rpt_mutex)) { cwiid_err(wiimote, "Mutex unlock error (rpt mutex) - " "deadlock warning"); return -1; } return 0; } transfermii-0.6.1/cwiid/thread.c0000644000175200017540000001751510751650020016114 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2007-05-16 L. Donnie Smith * * send error_mesg from process_error * * 2007-05-14 L. Donnie Smith * * added timestamp to message array * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul (renamed from event.c) * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-08 L. Donnie Smith * * fixed incompatible pointer warning in process_error * * 2007-04-08 Petter Reinholdtsen * * fixed signed/unsigned comparison error in int_listen * * 2007-04-04 L. Donnie Smith * * implemented process_error to handle socket read errors * * added rw_status triggers to read and write handlers * * 2007-03-14 L. Donnie Smith * * audit error checking * * reorganized file * * moved int_listen read/write code to process_read and process_write * * updated (some/a few) comments * * 2007-03-06 L. Donnie Smith * * added wiimote parameter to cwiid_err calls * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog * * type audit (stdint, const, char booleans) */ #include #include #include #include #include #include #include "cwiid_internal.h" #define READ_BUF_LEN 23 void *router_thread(struct wiimote *wiimote) { unsigned char buf[READ_BUF_LEN]; ssize_t len; struct mesg_array ma; char err, print_clock_err = 1; while (1) { /* Read packet */ len = read(wiimote->int_socket, buf, READ_BUF_LEN); ma.count = 0; if (clock_gettime(CLOCK_REALTIME, &ma.timestamp)) { if (print_clock_err) { cwiid_err(wiimote, "clock_gettime error"); print_clock_err = 0; } } err = 0; if ((len == -1) || (len == 0)) { process_error(wiimote, len, &ma); write_mesg_array(wiimote, &ma); /* Quit! */ break; } else { /* Verify first byte (DATA/INPUT) */ if (buf[0] != (BT_TRANS_DATA | BT_PARAM_INPUT)) { cwiid_err(wiimote, "Invalid packet type"); } /* Main switch */ switch (buf[1]) { case RPT_STATUS: err = process_status(wiimote, &buf[2], &ma); break; case RPT_BTN: err = process_btn(wiimote, &buf[2], &ma); break; case RPT_BTN_ACC: err = process_btn(wiimote, &buf[2], &ma) || process_acc(wiimote, &buf[4], &ma); break; case RPT_BTN_EXT8: err = process_btn(wiimote, &buf[2], &ma) || process_ext(wiimote, &buf[4], 8, &ma); break; case RPT_BTN_ACC_IR12: err = process_btn(wiimote, &buf[2], &ma) || process_acc(wiimote, &buf[4], &ma) || process_ir12(wiimote, &buf[7], &ma); break; case RPT_BTN_EXT19: err = process_btn(wiimote, &buf[2], &ma) || process_ext(wiimote, &buf[4], 19, &ma); break; case RPT_BTN_ACC_EXT16: err = process_btn(wiimote, &buf[2], &ma) || process_acc(wiimote, &buf[4], &ma) || process_ext(wiimote, &buf[7], 16, &ma); break; case RPT_BTN_IR10_EXT9: err = process_btn(wiimote, &buf[2], &ma) || process_ir10(wiimote, &buf[4], &ma) || process_ext(wiimote, &buf[14], 9, &ma); break; case RPT_BTN_ACC_IR10_EXT6: err = process_btn(wiimote, &buf[2], &ma) || process_acc(wiimote, &buf[4], &ma) || process_ir10(wiimote, &buf[7], &ma) || process_ext(wiimote, &buf[17], 6, &ma); break; case RPT_EXT21: err = process_ext(wiimote, &buf[2], 21, &ma); break; case RPT_BTN_ACC_IR36_1: case RPT_BTN_ACC_IR36_2: cwiid_err(wiimote, "Unsupported report type received " "(interleaved data)"); err = 1; break; case RPT_READ_DATA: err = process_read(wiimote, &buf[4]) || process_btn(wiimote, &buf[2], &ma); break; case RPT_WRITE_ACK: err = process_write(wiimote, &buf[2]); break; default: cwiid_err(wiimote, "Unknown message type"); err = 1; break; } if (!err && (ma.count > 0)) { if (update_state(wiimote, &ma)) { cwiid_err(wiimote, "State update error"); } if (wiimote->flags & CWIID_FLAG_MESG_IFC) { /* prints its own errors */ write_mesg_array(wiimote, &ma); } } } } return NULL; } void *status_thread(struct wiimote *wiimote) { struct mesg_array ma; struct cwiid_status_mesg *status_mesg; unsigned char buf; ma.count = 1; status_mesg = &ma.array[0].status_mesg; while (1) { if (full_read(wiimote->status_pipe[0], status_mesg, sizeof *status_mesg)) { cwiid_err(wiimote, "Pipe read error (status)"); /* Quit! */ break; } if (status_mesg->type != CWIID_MESG_STATUS) { cwiid_err(wiimote, "Bad message on status pipe"); continue; } if (status_mesg->ext_type == CWIID_EXT_UNKNOWN) { if (wiimote->state.ext_type == CWIID_EXT_NONE) { buf = 0x00; /* Initialize extension register space */ if (cwiid_write(wiimote, CWIID_RW_REG, 0xA40040, 1, &buf)) { cwiid_err(wiimote, "Extension initialization error"); status_mesg->ext_type = CWIID_EXT_UNKNOWN; } /* Read extension ID */ else if (cwiid_read(wiimote, CWIID_RW_REG | CWIID_RW_DECODE, 0xA400FE, 1, &buf)) { cwiid_err(wiimote, "Read error (extension error)"); status_mesg->ext_type = CWIID_EXT_UNKNOWN; } else { switch (buf) { case EXT_NONE: case EXT_PARTIAL: status_mesg->ext_type = CWIID_EXT_NONE; break; case EXT_NUNCHUK: status_mesg->ext_type = CWIID_EXT_NUNCHUK; break; case EXT_CLASSIC: status_mesg->ext_type = CWIID_EXT_CLASSIC; break; default: status_mesg->ext_type = CWIID_EXT_UNKNOWN; break; } } } else { status_mesg->ext_type = wiimote->state.ext_type; } } if (update_state(wiimote, &ma)) { cwiid_err(wiimote, "State update error"); } if (update_rpt_mode(wiimote, -1)) { cwiid_err(wiimote, "Error reseting report mode"); } if ((wiimote->state.rpt_mode & CWIID_RPT_STATUS) && (wiimote->flags & CWIID_FLAG_MESG_IFC)) { if (write_mesg_array(wiimote, &ma)) { /* prints its own errors */ } } } return NULL; } void *mesg_callback_thread(struct wiimote *wiimote) { int mesg_pipe = wiimote->mesg_pipe[0]; cwiid_mesg_callback_t *callback = wiimote->mesg_callback; struct mesg_array ma; int cancelstate; while (1) { if (read_mesg_array(mesg_pipe, &ma)) { cwiid_err(wiimote, "Mesg pipe read error"); continue; } /* TODO: The callback can still be called once after disconnect, * although it's very unlikely. User must keep track and avoid * accessing the wiimote struct after disconnect. */ if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate)) { cwiid_err(wiimote, "Cancel state disable error (callback thread)"); } callback(wiimote, ma.count, ma.array, &ma.timestamp); if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelstate)) { cwiid_err(wiimote, "Cancel state restore error (callback thread)"); } } return NULL; } transfermii-0.6.1/cwiid/util.c0000644000175200017540000001427510751650020015622 0ustar shinboshinbo/* Copyright (C) 2007 L. Donnie Smith * * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * ChangeLog: * 2008-08-14 L. Donnie Smith * * make cwiid_err_default public * * clean up cwiid_err * * 2007-04-24 L. Donnie Smith * * rewrite for API overhaul * * 2007-04-09 L. Donnie Smith * * renamed wiimote to libcwiid, renamed structures accordingly * * 2007-04-08 Petter Reinholdtsen * * fixed signed/unsigned comparison warning in send_report and * exec_write_seq * * 2007-04-01 L. Donnie Smith * * removed cwiid_findfirst (moved to bluetooth.c) * * 2007-03-27 L. Donnie Smith * * moved cwiid_findfirst to bluetooth.c * * 2007-03-14 L. Donnie Smith * * audited error checking (coda and error handler sections) * * 2007-03-05 L. Donnie Smith * * created cwiid_err_func variable * * created cwiid_err_default * * added wiimote parameter to cwiid_err definition and calls * * 2007-03-01 L. Donnie Smith * * Initial ChangeLog * * type audit (stdint, const, char booleans) */ #include #include #include #include #include #include #include #include #include "cwiid_internal.h" cwiid_err_t cwiid_err_default; static cwiid_err_t *cwiid_err_func = &cwiid_err_default; int cwiid_set_err(cwiid_err_t *err) { /* TODO: assuming pointer assignment is atomic operation */ /* if it is, and the user doesn't care about race conditions, we don't * either */ cwiid_err_func = err; return 0; } void cwiid_err_default(struct wiimote *wiimote, const char *str, va_list ap) { vfprintf(stderr, str, ap); fprintf(stderr, "\n"); } void cwiid_err(struct wiimote *wiimote, const char *str, ...) { va_list ap; if (cwiid_err_func) { va_start(ap, str); (*cwiid_err_func)(wiimote, str, ap); va_end(ap); } } int verify_handshake(struct wiimote *wiimote) { unsigned char handshake; if (read(wiimote->ctl_socket, &handshake, 1) != 1) { cwiid_err(wiimote, "Socket read error (handshake)"); return -1; } else if ((handshake & BT_TRANS_MASK) != BT_TRANS_HANDSHAKE) { cwiid_err(wiimote, "Handshake expected, non-handshake received"); return -1; } else if ((handshake & BT_PARAM_MASK) != BT_PARAM_SUCCESSFUL) { cwiid_err(wiimote, "Non-successful handshake"); return -1; } return 0; } #define SEND_RPT_BUF_LEN 23 int send_report(struct wiimote *wiimote, uint8_t flags, uint8_t report, size_t len, const void *data) { unsigned char buf[SEND_RPT_BUF_LEN]; if ((len+2) > SEND_RPT_BUF_LEN) { return -1; } buf[0] = BT_TRANS_SET_REPORT | BT_PARAM_OUTPUT; buf[1] = report; memcpy(buf+2, data, len); if (!(flags & SEND_RPT_NO_RUMBLE)) { buf[2] |= wiimote->state.rumble; } if (write(wiimote->ctl_socket, buf, len+2) != (ssize_t)(len+2)) { return -1; } else if (verify_handshake(wiimote)) { return -1; } return 0; } int exec_write_seq(struct wiimote *wiimote, unsigned int len, struct write_seq *seq) { unsigned int i; for (i=0; i < len; i++) { switch (seq[i].type) { case WRITE_SEQ_RPT: if (send_report(wiimote, seq[i].flags, seq[i].report_offset, seq[i].len, seq[i].data)) { return -1; } break; case WRITE_SEQ_MEM: if (cwiid_write(wiimote, seq[i].flags, seq[i].report_offset, seq[i].len, seq[i].data)) { return -1; } break; } } return 0; } int full_read(int fd, void *buf, size_t len) { ssize_t last_len = 0; do { if ((last_len = read(fd, buf, len)) == -1) { return -1; } len -= last_len; buf += last_len; } while (len > 0); return 0; } int write_mesg_array(struct wiimote *wiimote, struct mesg_array *ma) { ssize_t len = (void *)&ma->array[ma->count] - (void *)ma; int ret = 0; /* This must remain a single write operation to ensure atomicity, * which is required to avoid mutexes and cancellation issues */ if (write(wiimote->mesg_pipe[1], ma, len) != len) { if (errno == EAGAIN) { cwiid_err(wiimote, "Mesg pipe overflow"); if (fcntl(wiimote->mesg_pipe[1], F_SETFL, 0)) { cwiid_err(wiimote, "File control error (mesg pipe)"); ret = -1; } else { if (write(wiimote->mesg_pipe[1], ma, len) != len) { cwiid_err(wiimote, "Pipe write error (mesg pipe)"); ret = -1; } if (fcntl(wiimote->mesg_pipe[1], F_SETFL, O_NONBLOCK)) { cwiid_err(wiimote, "File control error (mesg pipe"); } } } else { cwiid_err(wiimote, "Pipe write error (mesg pipe)"); ret = -1; } } return ret; } int read_mesg_array(int fd, struct mesg_array *ma) { ssize_t len; len = (void *)&ma->array[0] - (void *)ma; if (full_read(fd, ma, len)) { return -1; } len = ma->count * sizeof ma->array[0]; if (full_read(fd, &ma->array[0], len)) { return -1; } return 0; } int cancel_rw(struct wiimote *wiimote) { struct rw_mesg rw_mesg; rw_mesg.type = RW_CANCEL; if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) != sizeof rw_mesg) { cwiid_err(wiimote, "Pipe write error (rw)"); return -1; } return 0; } int cancel_mesg_callback(struct wiimote *wiimote) { int ret = 0; if (pthread_cancel(wiimote->mesg_callback_thread)) { cwiid_err(wiimote, "Thread cancel error (callback thread)"); ret = -1; } if (pthread_detach(wiimote->mesg_callback_thread)) { cwiid_err(wiimote, "Thread detach error (callback thread)"); ret = -1; } return ret; } transfermii-0.6.1/emptymii.mii0000644000175200017540000000011210751645145015734 0ustar shinboshinbotransfermii-0.6.1/gui/0000755000175200017540000000000010763522142014163 5ustar shinboshinbotransfermii-0.6.1/gui/Makefile.old0000644000175200017540000000101310751657047016405 0ustar shinboshinbo#Copyright (C) 2007-2008 Arnaud Ysmal CC=gcc SRCS=transfermii_gui.c pageAbout.c pageLocal.c pageWiimote.c OBJS=$(SRCS:.c=.o) LDOPTS= `pkg-config gtk+-2.0 --libs` -L../cwiid -L../tmii -lcwiid -ltmii -lbluetooth -lpthread -lrt CFLAGS=-Wall -Werror `pkg-config gtk+-2.0 --cflags` BIN=transfermii_gui all: $(BIN) %.o : %.c $(CC) -o $@ -c $< $(CFLAGS) $(BIN): $(OBJS) ../tmii/libtmii.a ../cwiid/libcwiid.a $(CC) $(LDOPTS) $^ -o ../$(BIN) run: ../$(BIN) clean: -rm ${OBJS} mrproper: -rm ../$(BIN) transfermii-0.6.1/gui/pageAbout.c0000644000175200017540000000567310751650450016252 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageAbout.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "pageAbout.h" GtkWidget* createPageAbout(void){ GtkWidget *mainVBox; GtkWidget *frame; GtkWidget *label; GtkWidget *textView; GtkWidget *scrolledWindow; GtkWidget *authorsVBox; GtkTextBuffer *buffer; GtkTextIter iter; /* Main vbox initialisation */ mainVBox=gtk_vbox_new(FALSE, 0); /* Authors frame */ frame=gtk_frame_new("Authors"); gtk_container_set_border_width(GTK_CONTAINER(frame), 10); authorsVBox=gtk_vbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(authorsVBox), 10); label=gtk_label_new("Main Program : Arnaud Ysmal"); gtk_box_pack_start(GTK_BOX(authorsVBox), label, FALSE, TRUE, 0); label=gtk_label_new("GUI : Marylene Ysmal"); gtk_box_pack_start(GTK_BOX(authorsVBox), label, FALSE, TRUE, 0); label=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(authorsVBox), label, FALSE, TRUE, 0); label=gtk_label_new("Contact : wiidevel@stacktic.org"); gtk_box_pack_start(GTK_BOX(authorsVBox), label, FALSE, TRUE, 0); gtk_container_add(GTK_CONTAINER(frame), authorsVBox); gtk_box_pack_start(GTK_BOX(mainVBox), frame, FALSE, TRUE, 0); /* License frame */ frame=gtk_frame_new("License"); gtk_container_set_border_width(GTK_CONTAINER(frame), 10); /* Scrolled Window */ scrolledWindow=gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); /* TextView */ textView=gtk_text_view_new(); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textView),GTK_WRAP_WORD); gtk_container_set_border_width(GTK_CONTAINER(textView), 10); gtk_text_view_set_editable(GTK_TEXT_VIEW(textView),FALSE); gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textView),FALSE); /* Filling the TextView */ buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textView)); gtk_text_buffer_set_text(buffer, "", 0); gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0); gtk_text_buffer_insert(buffer, &iter, TMII_LICENSE, -1); gtk_container_add(GTK_CONTAINER(scrolledWindow), textView); gtk_container_add(GTK_CONTAINER(frame), scrolledWindow); gtk_box_pack_start(GTK_BOX(mainVBox), frame, TRUE, TRUE, 0); return mainVBox; } transfermii-0.6.1/gui/pageAbout.h0000644000175200017540000000320110751650463016244 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageAbout.h (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PAGE_ABOUT_H #define _PAGE_ABOUT_H #include #include GtkWidget* createPageAbout(void); #define TMII_LICENSE "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. \n\n\ 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 General Public License for more details.\n\n\ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA" #endif transfermii-0.6.1/gui/pageLocal.c0000644000175200017540000001373110751650477016235 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageLocal.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "pageLocal.h" extern void updateStatusBar(char *msg); static void onFileButton(void); static void onUpdateButton(void); static GtkWidget *fileButton; static GtkWidget *nameEntry; static GtkWidget *creatorEntry; static GtkWidget *sexRadioMale; static GtkWidget *sexRadioFemale; static GtkWidget *updateButton; GtkWidget* createPageLocal(void){ GtkWidget *frame; GtkWidget *label; GtkWidget *mainVBox; GtkWidget *HBox; GtkWidget *VButtonBox; GtkWidget *table; GSList *group; /* Main vbox initialisation */ mainVBox=gtk_vbox_new(FALSE, 0); /* File frame */ frame=gtk_frame_new("Select a local file"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); HBox=gtk_hbox_new(TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(HBox), 5); fileButton=gtk_file_chooser_button_new("Choose a Mii file", GTK_FILE_CHOOSER_ACTION_OPEN); g_signal_connect_swapped(G_OBJECT(fileButton), "selection-changed", G_CALLBACK(onFileButton), NULL); gtk_box_pack_start(GTK_BOX(HBox), fileButton, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(frame), HBox); gtk_box_pack_start(GTK_BOX(mainVBox), frame, FALSE, FALSE, 0); /* Details frame */ frame=gtk_frame_new("Details"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); HBox=gtk_hbox_new(FALSE, 0); table=gtk_table_new(3, 3, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table),5); gtk_table_set_col_spacings(GTK_TABLE(table),5); label=gtk_label_new("Name : "); nameEntry=gtk_entry_new(); gtk_widget_set_sensitive(nameEntry, FALSE); gtk_entry_set_max_length(GTK_ENTRY(nameEntry), 10); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), nameEntry, 1, 3, 0, 1); label=gtk_label_new("Sex : "); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); sexRadioMale=gtk_radio_button_new_with_label (NULL, "Male"); gtk_table_attach_defaults(GTK_TABLE(table), sexRadioMale, 1, 2, 1, 2); group=gtk_radio_button_get_group(GTK_RADIO_BUTTON (sexRadioMale)); sexRadioFemale=gtk_radio_button_new_with_label(group, "Female"); gtk_widget_set_sensitive(sexRadioFemale, FALSE); gtk_widget_set_sensitive(sexRadioMale, FALSE); gtk_table_attach_defaults(GTK_TABLE(table), sexRadioFemale, 2, 3, 1, 2); label=gtk_label_new("Creator : "); creatorEntry=gtk_entry_new(); gtk_widget_set_sensitive(creatorEntry, FALSE); gtk_entry_set_max_length(GTK_ENTRY(creatorEntry), 10); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); gtk_table_attach_defaults(GTK_TABLE(table), creatorEntry, 1, 3, 2, 3); gtk_box_pack_start(GTK_BOX(HBox), table, TRUE, TRUE, 0); VButtonBox=gtk_vbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(VButtonBox),GTK_BUTTONBOX_SPREAD); updateButton=gtk_button_new_with_label("Update"); g_signal_connect_swapped(G_OBJECT(updateButton), "clicked", G_CALLBACK(onUpdateButton), NULL); gtk_widget_set_sensitive(updateButton, FALSE); gtk_container_add(GTK_CONTAINER(VButtonBox), updateButton); gtk_box_pack_start(GTK_BOX(HBox), VButtonBox, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(frame), HBox); gtk_box_pack_start(GTK_BOX(mainVBox), frame, FALSE, FALSE, 0); return mainVBox; } void onFileButton(void){ if(fileRead(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileButton)))){ if(miiIsEmpty(0)) { gtk_widget_set_sensitive(nameEntry, FALSE); gtk_widget_set_sensitive(creatorEntry, FALSE); gtk_widget_set_sensitive(sexRadioFemale, FALSE); gtk_widget_set_sensitive(sexRadioMale, FALSE); gtk_widget_set_sensitive(updateButton, FALSE); updateStatusBar("mii empty"); return; } else { gtk_widget_set_sensitive(nameEntry, TRUE); gtk_widget_set_sensitive(creatorEntry, TRUE); gtk_widget_set_sensitive(sexRadioFemale, TRUE); gtk_widget_set_sensitive(sexRadioMale, TRUE); gtk_widget_set_sensitive(updateButton, TRUE); } char buffMiiName[MII_NAME_LENGTH_CHAR+1]; char buffMiiCreator[MII_CREATOR_LENGTH_CHAR+1]; getMiiNameAscii(buffMiiName, 0); getMiiCreatorAscii(buffMiiCreator, 0); gtk_entry_set_text(GTK_ENTRY(nameEntry), buffMiiName); gtk_entry_set_text(GTK_ENTRY(creatorEntry), buffMiiCreator); if(getMiiSex(0) == 'F') gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioFemale), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioMale), TRUE); } else updateStatusBar("Error reading file"); return; } void onUpdateButton(void){ /* if(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileButton)) == NULL){ updateStatusBar("Please select a file\n"); return; } */ if(!(setMiiNameAscii((char*) gtk_entry_get_text(GTK_ENTRY(nameEntry)),0))){ updateStatusBar("Error setting name"); return; } if(!(setMiiCreatorAscii((char *)gtk_entry_get_text(GTK_ENTRY(creatorEntry)),0))){ updateStatusBar("Error setting creator"); return; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sexRadioFemale))){ if(!(setMiiSex('F', 0))){ updateStatusBar("Error setting sex"); return; } } else { if(!(setMiiSex('M', 0))){ updateStatusBar("Error setting sex"); return; } } fileWrite(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileButton)), 0); return; } transfermii-0.6.1/gui/pageLocal.h0000644000175200017540000000172610751650507016235 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageLocal.h (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PAGE_LOCAL_H #define _PAGE_LOCAL_H #include #include #include "../tmii/tmii.h" GtkWidget* createPageLocal(void); #endif transfermii-0.6.1/gui/pageWiimote.c0000644000175200017540000005367710763517042016626 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageWiimote.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "pageWiimote.h" static void onWiimoteMacCheck(void); static void onWiiMacCheck(void); static void onDownloadButton(void); static void onUploadFileButton(void); static void onDeleteButton(void); static void onChangeMacButton(void); static void onConnectButton(void); static void onUpdateButton(void); static void onDisconnectButton(void); static void onSelectionChanged(void); extern void updateStatusBar(char *msg); static GtkWidget *wiimoteMacCheck; static GtkWidget *wiimoteMacEntry; static GtkWidget *wiiMacCheck; static GtkWidget *wiiMacEntry; static GtkWidget *nameEntry; static GtkWidget *creatorEntry; static GtkWidget *sexRadioMale; static GtkWidget *sexRadioFemale; static GtkWidget *macLabel; static GtkWidget *connectButton; static GtkWidget *updateButton; static GtkWidget *disconnectButton; static GtkWidget *view; static GtkWidget *uploadFileButton; static GtkWidget *downloadButton; static GtkWidget *deleteButton; static GtkWidget *changeMacButton; static int old_slot = 0; GtkWidget* createPageWiimote(){ GtkWidget *frame; GtkWidget *label; GtkWidget *mainVBox; GtkWidget *HBox; GtkWidget *VBox; GtkWidget *ButtonBox; GtkWidget *table; GtkCellRenderer *renderer; GtkTreeModel *model; GtkListStore *store; GtkTreeIter tree_iter; GSList *group; GdkColor color; char bufferchar[1024]; int i; /* Main vbox initialisation */ mainVBox=gtk_vbox_new(FALSE, 0); /* Wiimote's MAC Address frame */ frame=gtk_frame_new("Wiimote's MAC address"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); HBox=gtk_hbox_new(FALSE,5); gtk_container_set_border_width(GTK_CONTAINER(HBox), 5); gtk_container_add(GTK_CONTAINER(frame), HBox); wiimoteMacCheck=gtk_check_button_new_with_label("Automatic"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wiimoteMacCheck), TRUE); g_signal_connect_swapped(G_OBJECT(wiimoteMacCheck), "toggled", G_CALLBACK(onWiimoteMacCheck), NULL); gtk_box_pack_start(GTK_BOX(HBox), wiimoteMacCheck, TRUE, TRUE, 5); label=gtk_label_new("00:19:1D:"); gtk_box_pack_start(GTK_BOX(HBox), label, FALSE, FALSE, 0); wiimoteMacEntry=gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(wiimoteMacEntry), 8); gtk_box_pack_start(GTK_BOX(HBox), wiimoteMacEntry, TRUE, TRUE, 0); gtk_widget_set_sensitive(wiimoteMacEntry, FALSE); label=gtk_label_new("(XX:XX:XX)"); gtk_box_pack_start(GTK_BOX(HBox), label, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(mainVBox), frame, TRUE, TRUE, 0); /* Wii's MAC Address frame */ frame=gtk_frame_new("Wii's MAC address"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); HBox=gtk_hbox_new(FALSE,5); gtk_container_set_border_width(GTK_CONTAINER(HBox), 5); gtk_container_add(GTK_CONTAINER(frame), HBox); wiiMacCheck=gtk_check_button_new_with_label("Automatic"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wiiMacCheck), TRUE); g_signal_connect_swapped(G_OBJECT(wiiMacCheck), "toggled", G_CALLBACK(onWiiMacCheck), NULL); gtk_box_pack_start(GTK_BOX(HBox), wiiMacCheck, TRUE, TRUE, 5); label=gtk_label_new("00:17:AB:"); gtk_box_pack_start(GTK_BOX(HBox), label, FALSE, FALSE, 0); wiiMacEntry=gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(wiiMacEntry), 8); gtk_box_pack_start(GTK_BOX(HBox), wiiMacEntry, TRUE, TRUE, 0); gtk_widget_set_sensitive(wiiMacEntry, FALSE); label=gtk_label_new("(XX:XX:XX)"); gtk_box_pack_start(GTK_BOX(HBox), label, TRUE, TRUE, 5); gtk_box_pack_start(GTK_BOX(mainVBox), frame, TRUE, TRUE, 0); /* Wiimote's Slots frame */ frame=gtk_frame_new("Wiimote's Slots"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); view=gtk_tree_view_new(); gtk_widget_set_sensitive(view, FALSE); renderer=gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, "Slots", renderer, "text", 0, NULL); store=gtk_list_store_new(1, G_TYPE_STRING); for(i=1;i<=10;i++){ sprintf(bufferchar, "Slot %i", i); gtk_list_store_append(store, &tree_iter); gtk_list_store_set(store, &tree_iter, 0, bufferchar, -1); } model=GTK_TREE_MODEL(store); gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); g_object_unref(model); g_signal_connect_swapped(G_OBJECT(view), "cursor_changed", G_CALLBACK(onSelectionChanged), NULL); HBox=gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(HBox), 5); gtk_box_pack_start(GTK_BOX(HBox), view, TRUE, TRUE, 0); VBox=gtk_vbox_new(FALSE, 0); table=gtk_table_new(3, 3, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table),5); gtk_table_set_col_spacings(GTK_TABLE(table),5); label=gtk_label_new("Name : "); nameEntry=gtk_entry_new(); gtk_widget_set_sensitive(nameEntry, FALSE); gtk_entry_set_max_length(GTK_ENTRY(nameEntry), 10); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), nameEntry, 1, 3, 0, 1); label=gtk_label_new("Sex : "); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); sexRadioMale=gtk_radio_button_new_with_label(NULL, "Male"); gtk_table_attach_defaults(GTK_TABLE(table), sexRadioMale, 1, 2, 1, 2); group=gtk_radio_button_get_group(GTK_RADIO_BUTTON(sexRadioMale)); gtk_widget_set_sensitive(sexRadioMale, FALSE); sexRadioFemale=gtk_radio_button_new_with_label(group, "Female"); gtk_table_attach_defaults(GTK_TABLE(table), sexRadioFemale, 2, 3, 1, 2); gtk_widget_set_sensitive(sexRadioFemale, FALSE); label=gtk_label_new("Creator : "); creatorEntry=gtk_entry_new(); gtk_widget_set_sensitive(creatorEntry, FALSE); gtk_entry_set_max_length(GTK_ENTRY(creatorEntry), 10); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3); gtk_table_attach_defaults(GTK_TABLE(table), creatorEntry, 1, 3, 2, 3); gtk_box_pack_start(GTK_BOX(VBox), table, TRUE, TRUE, 0); macLabel=gtk_label_new(""); gtk_box_pack_start(GTK_BOX(VBox), macLabel, TRUE, TRUE, 0); ButtonBox=gtk_vbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(ButtonBox),GTK_BUTTONBOX_SPREAD); downloadButton=gtk_button_new_with_label("Download"); g_signal_connect_swapped(G_OBJECT(downloadButton), "clicked", G_CALLBACK(onDownloadButton), NULL); gtk_widget_set_sensitive(downloadButton, FALSE); gtk_container_add(GTK_CONTAINER(ButtonBox), downloadButton); uploadFileButton=gtk_button_new_with_label("Upload File"); g_signal_connect_swapped(G_OBJECT(uploadFileButton), "clicked", G_CALLBACK(onUploadFileButton), NULL); gtk_widget_set_sensitive(uploadFileButton, FALSE); gtk_container_add(GTK_CONTAINER(ButtonBox), uploadFileButton); deleteButton=gtk_button_new_with_label("Delete"); g_signal_connect_swapped(G_OBJECT(deleteButton), "clicked", G_CALLBACK(onDeleteButton), NULL); gtk_widget_set_sensitive(deleteButton, FALSE); gtk_container_add(GTK_CONTAINER(ButtonBox), deleteButton); changeMacButton=gtk_button_new_with_label("Change MAC"); g_signal_connect_swapped(G_OBJECT(changeMacButton), "clicked", G_CALLBACK(onChangeMacButton), NULL); gtk_widget_set_sensitive(changeMacButton, FALSE); gtk_container_add(GTK_CONTAINER(ButtonBox), changeMacButton); gtk_box_pack_start(GTK_BOX(VBox), ButtonBox, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(HBox), VBox, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(frame), HBox); gtk_box_pack_start(GTK_BOX(mainVBox), frame, TRUE, TRUE, 0); /* Bluetooth frame */ frame=gtk_frame_new("Bluetooth"); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); ButtonBox=gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(ButtonBox),GTK_BUTTONBOX_SPREAD); gtk_container_set_border_width(GTK_CONTAINER(ButtonBox), 5); gtk_button_box_set_layout(GTK_BUTTON_BOX(ButtonBox),GTK_BUTTONBOX_SPREAD); connectButton=gtk_button_new_with_label("Connect"); g_signal_connect_swapped(G_OBJECT(connectButton), "clicked", G_CALLBACK(onConnectButton), NULL); gtk_container_add(GTK_CONTAINER(ButtonBox), connectButton); updateButton=gtk_button_new_with_label("Update"); g_signal_connect_swapped(G_OBJECT(updateButton), "clicked", G_CALLBACK(onUpdateButton), NULL); gtk_container_add(GTK_CONTAINER(ButtonBox), updateButton); gtk_widget_set_sensitive(updateButton, FALSE); disconnectButton=gtk_button_new_with_label("Disconnect"); g_signal_connect_swapped(G_OBJECT(disconnectButton), "clicked", G_CALLBACK(onDisconnectButton), NULL); gtk_container_add(GTK_CONTAINER(ButtonBox), disconnectButton); gtk_widget_set_sensitive(disconnectButton, FALSE); gtk_container_add(GTK_CONTAINER(frame), ButtonBox); color.pixel=32; color.green=color.blue=0x0000; color.red=0xFFFF; gtk_widget_modify_bg(connectButton, GTK_STATE_NORMAL, &color); gtk_widget_modify_bg(connectButton, GTK_STATE_PRELIGHT, &color); gtk_box_pack_start(GTK_BOX(mainVBox), frame, TRUE, TRUE, 0); return mainVBox; } void onWiimoteMacCheck(void) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiimoteMacCheck))) gtk_widget_set_sensitive(wiimoteMacEntry, FALSE); else gtk_widget_set_sensitive(wiimoteMacEntry, TRUE); } void onWiiMacCheck(void) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiiMacCheck))) { gtk_widget_set_sensitive(wiiMacEntry, FALSE); gtk_widget_set_sensitive(changeMacButton, FALSE); } else { gtk_widget_set_sensitive(wiiMacEntry, TRUE); if(wm_read && gtk_tree_selection_get_selected(selection, &model, &selected_row)) gtk_widget_set_sensitive(changeMacButton, TRUE); } } void onDownloadButton(void) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; int slot; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!wm_read || !gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; slot = (*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1; GtkWidget *chooserDialog = gtk_file_chooser_dialog_new("Download", NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL); gtk_window_set_modal(GTK_WINDOW(chooserDialog), TRUE); if(gtk_dialog_run(GTK_DIALOG(chooserDialog)) != GTK_RESPONSE_OK) { gtk_widget_destroy(chooserDialog); return; } char *fname = (char*)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooserDialog)); int size = strlen(fname)+strlen("Writing file ")+1; char *msg = malloc(size); snprintf(msg, size-1, "Writing file %s\n", fname); updateStatusBar(msg); free(msg); if(fileWrite(fname, slot)) updateStatusBar("File written"); else updateStatusBar("Writing error"); gtk_widget_destroy(chooserDialog); } void update(void); void onUploadFileButton(void) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; int slot; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!wm_read || !gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; slot = (*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1; GtkWidget *chooserDialog = gtk_file_chooser_dialog_new("Upload", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); gtk_window_set_modal(GTK_WINDOW(chooserDialog), TRUE); if(gtk_dialog_run(GTK_DIALOG(chooserDialog)) != GTK_RESPONSE_OK) { gtk_widget_destroy(chooserDialog); return; } char *fname = (char*)gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooserDialog)); int size = strlen(fname)+strlen("Reading file ")+1; char *msg = malloc(size); snprintf(msg, size-1, "Reading file %s\n", fname); updateStatusBar(msg); free(msg); if(addMii(fname, slot)) updateStatusBar("mii added"); else updateStatusBar("mii not added"); gtk_widget_destroy(chooserDialog); /*onSelectionChanged();*/ update(); } void onDeleteButton(void) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; int slot; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!wm_read || !gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; slot = (*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1; if(delMii(slot)) { char msg[] = "mii slot 0x deleted"; if(slot == 10) { msg[9] = '1'; msg[10] = '0'; } else if(slot<10) msg[10] = slot+'0'; updateStatusBar(msg); onSelectionChanged(); } } void onChangeMacButton(void) { GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; char tmp[11]; tmp[10] = '\0'; if(!wm_read || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiiMacCheck))) return; strncpy(tmp, (char*)gtk_entry_get_text(GTK_ENTRY(wiiMacEntry)), 10); if(!parseMacAddress(tmp)) { updateStatusBar("Mac address incorrect"); return; } selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; setMacAddress((*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1); onSelectionChanged(); } void onConnectButton(void) { GdkColor color; color.pixel=32; color.red=color.blue=0x0000; color.green=0xFFFF; if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiimoteMacCheck))) { char tmpmac[19]; snprintf(tmpmac, 18, "00:19:1D:%s", gtk_entry_get_text(GTK_ENTRY(wiimoteMacEntry))); str2ba(tmpmac, &ba); printf("Connecting to the wiimote...\n"); } else printf("Please press 1+2 on the wiimote\n"); if(!wiimoteConnect()) { updateStatusBar("Could not connect to the wiimote"); return; } if(!wiimoteRead()) { updateStatusBar("Could not read the wiimote"); return; } updateStatusBar("Connected"); gtk_widget_set_sensitive(view, TRUE); gtk_widget_set_sensitive(connectButton, FALSE); gtk_widget_set_sensitive(updateButton, TRUE); gtk_widget_set_sensitive(disconnectButton, TRUE); gtk_widget_modify_bg(connectButton, GTK_STATE_INSENSITIVE, &color); } void onUpdateButton(void) { if(!wm_read) return; GtkWidget *msgDialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, "Update the wiimote ?"); if(gtk_dialog_run(GTK_DIALOG(msgDialog)) != GTK_RESPONSE_OK) { gtk_widget_destroy(msgDialog); return; } wm_update=TRUE; wiimoteWrite(); gtk_widget_destroy(msgDialog); updateStatusBar("Updating..."); if(wiimoteWrite()) updateStatusBar("Updated"); else updateStatusBar("Update Error"); } void onDisconnectButton(void) { GdkColor color; color.pixel=32; color.green=color.blue=0x0000; color.red=0xFFFF; extern bool wm_auto_update; GtkWidget *msgDialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Update the wiimote before disconnecting ?"); if(gtk_dialog_run(GTK_DIALOG(msgDialog)) == GTK_RESPONSE_YES) { wm_auto_update=TRUE; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; selection=gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(gtk_tree_selection_get_selected(selection, &model, &selected_row)) { int slot =((*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0')+1; char *name, buff[MII_NAME_LENGTH_CHAR+1]; name = (char*)gtk_entry_get_text(GTK_ENTRY(nameEntry)); getMiiNameAscii(buff, slot); if(*name && strcmp(buff, name)) { setMiiNameAscii(name, slot); wm_update = TRUE; } name = (char*)gtk_entry_get_text(GTK_ENTRY(creatorEntry)); getMiiCreatorAscii(buff, slot); if(*name && strcmp(buff, name)) { setMiiCreatorAscii(name, slot); wm_update = TRUE; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sexRadioMale)) && getMiiSex(slot)=='F') { setMiiSex('M', slot); wm_update = TRUE; } else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sexRadioFemale)) && getMiiSex(slot)=='M') { setMiiSex('F', slot); wm_update = TRUE; } } } gtk_widget_destroy(msgDialog); wiimoteDisconnect(); gtk_widget_set_sensitive(view, FALSE); gtk_widget_set_sensitive(nameEntry, FALSE); gtk_widget_set_sensitive(creatorEntry, FALSE); gtk_widget_set_sensitive(sexRadioFemale, FALSE); gtk_widget_set_sensitive(sexRadioMale, FALSE); gtk_widget_set_sensitive(downloadButton, FALSE); gtk_widget_set_sensitive(uploadFileButton, FALSE); gtk_widget_set_sensitive(deleteButton, FALSE); gtk_widget_set_sensitive(changeMacButton, FALSE); gtk_widget_set_sensitive(connectButton, TRUE); gtk_widget_set_sensitive(updateButton, FALSE); gtk_widget_set_sensitive(disconnectButton, FALSE); gtk_widget_modify_bg(connectButton, GTK_STATE_INSENSITIVE, &color); gtk_label_set_text(GTK_LABEL(macLabel), ""); gtk_entry_set_text(GTK_ENTRY(nameEntry), ""); gtk_entry_set_text(GTK_ENTRY(creatorEntry), ""); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioMale), TRUE); updateStatusBar("Disconnected"); } void onSelectionChanged(void) { int slot; char buffMiiName[MII_NAME_LENGTH_CHAR+1]; char buffMiiCreator[MII_CREATOR_LENGTH_CHAR+1]; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; selection=gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!wm_read || !gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; slot=((*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1); if(old_slot && !miiIsEmpty(slot)) { char *name, buff[MII_NAME_LENGTH_CHAR+1]; name = (char*)gtk_entry_get_text(GTK_ENTRY(nameEntry)); getMiiNameAscii(buff, old_slot); if(*name && strcmp(buff, name)) { setMiiNameAscii(name, old_slot); wm_update = TRUE; } name = (char*)gtk_entry_get_text(GTK_ENTRY(creatorEntry)); getMiiCreatorAscii(buff, old_slot); if(*name && strcmp(buff, name)) { setMiiCreatorAscii(name, old_slot); wm_update = TRUE; } if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sexRadioMale)) && getMiiSex(old_slot)=='F') { setMiiSex('M', old_slot); wm_update = TRUE; } else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sexRadioFemale)) && getMiiSex(old_slot)=='M') { setMiiSex('F', old_slot); wm_update = TRUE; } } old_slot = slot; if(miiIsEmpty(slot)) { gtk_widget_set_sensitive(downloadButton, FALSE); gtk_widget_set_sensitive(uploadFileButton, TRUE); gtk_widget_set_sensitive(deleteButton, FALSE); gtk_widget_set_sensitive(changeMacButton, FALSE); gtk_widget_set_sensitive(nameEntry, FALSE); gtk_widget_set_sensitive(creatorEntry, FALSE); gtk_widget_set_sensitive(sexRadioFemale, FALSE); gtk_widget_set_sensitive(sexRadioMale, FALSE); gtk_label_set_text(GTK_LABEL(macLabel), ""); } else { gtk_widget_set_sensitive(downloadButton, TRUE); gtk_widget_set_sensitive(uploadFileButton, TRUE); gtk_widget_set_sensitive(deleteButton, TRUE); gtk_widget_set_sensitive(nameEntry, TRUE); gtk_widget_set_sensitive(creatorEntry, TRUE); gtk_widget_set_sensitive(sexRadioFemale, TRUE); gtk_widget_set_sensitive(sexRadioMale, TRUE); unsigned char mactmp[3]; char labtmp[23+9+9]; getMiiMacAddress(mactmp, slot); snprintf(labtmp, 40, "Current mac address : 00:17:ab:%2x:%2x:%2x", mactmp[0], mactmp[1], mactmp[2]); gtk_label_set_text(GTK_LABEL(macLabel), labtmp); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiiMacCheck))) gtk_widget_set_sensitive(changeMacButton, FALSE); else gtk_widget_set_sensitive(changeMacButton, TRUE); } getMiiNameAscii(buffMiiName, slot); gtk_entry_set_text(GTK_ENTRY(nameEntry), buffMiiName); getMiiCreatorAscii(buffMiiCreator, slot); gtk_entry_set_text(GTK_ENTRY(creatorEntry), buffMiiCreator); if(getMiiSex(slot) == 'F') gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioFemale), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioMale), TRUE); } void update(void) { int slot; char buffMiiName[MII_NAME_LENGTH_CHAR+1]; char buffMiiCreator[MII_CREATOR_LENGTH_CHAR+1]; unsigned char mactmp[3]; char labtmp[23+9+9]; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter selected_row; selection=gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); if(!wm_read || !gtk_tree_selection_get_selected(selection, &model, &selected_row)) return; slot=((*gtk_tree_model_get_string_from_iter(model,&selected_row))-'0'+1); gtk_widget_set_sensitive(downloadButton, TRUE); gtk_widget_set_sensitive(uploadFileButton, TRUE); gtk_widget_set_sensitive(deleteButton, TRUE); gtk_widget_set_sensitive(nameEntry, TRUE); gtk_widget_set_sensitive(creatorEntry, TRUE); gtk_widget_set_sensitive(sexRadioFemale, TRUE); gtk_widget_set_sensitive(sexRadioMale, TRUE); getMiiMacAddress(mactmp, slot); snprintf(labtmp, 40, "Current mac address : 00:17:ab:%2x:%2x:%2x", mactmp[0], mactmp[1], mactmp[2]); gtk_label_set_text(GTK_LABEL(macLabel), labtmp); if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wiiMacCheck))) gtk_widget_set_sensitive(changeMacButton, FALSE); else gtk_widget_set_sensitive(changeMacButton, TRUE); getMiiNameAscii(buffMiiName, slot); gtk_entry_set_text(GTK_ENTRY(nameEntry), buffMiiName); getMiiCreatorAscii(buffMiiCreator, slot); gtk_entry_set_text(GTK_ENTRY(creatorEntry), buffMiiCreator); if(getMiiSex(slot) == 'F') gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioFemale), TRUE); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sexRadioMale), TRUE); } transfermii-0.6.1/gui/pageWiimote.h0000644000175200017540000000210310751650532016604 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * pageWiimote.h (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _PAGE_WIIMOTE_H #define _PAGE_WIIMOTE_H #include #include #include #include #include #include #include #include "../tmii/tmii.h" GtkWidget* createPageWiimote(); #endif transfermii-0.6.1/gui/transfermii_gui.c0000644000175200017540000000723410751650550017526 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Marylene Ysmal * * transfermii_gui.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include "pageAbout.h" #include "pageLocal.h" #include "pageWiimote.h" static void onQuitButton(GtkWidget *widget, gpointer data); void updateStatusBar(char *msg); GtkWidget *statusBar; int main(int argc, char **argv){ GtkWidget *window; GtkWidget *notebook; /* Pages widgets */ GtkWidget *wAbout; GtkWidget *wLocal; GtkWidget *wWiimote; GtkWidget *pagesLabel; GtkWidget *mainVBox; GtkWidget *buttonBox; GtkWidget *quitButton; gtk_init(&argc, &argv); /* Main window initialisation */ window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Transfermii !"); gtk_window_set_default_size(GTK_WINDOW(window), 600, 400); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(onQuitButton), NULL); /* Notebook initialisation */ notebook=gtk_notebook_new(); gtk_container_set_border_width(GTK_CONTAINER(notebook), 10); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook),GTK_POS_TOP); mainVBox=gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), mainVBox); gtk_box_pack_start(GTK_BOX(mainVBox), notebook, TRUE, TRUE, 0); /* Adding pages to the notebook */ pagesLabel=gtk_label_new("Wiimote"); wWiimote=createPageWiimote(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), wWiimote, pagesLabel); pagesLabel=gtk_label_new("Local Files"); wLocal=createPageLocal(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), wLocal, pagesLabel); pagesLabel=gtk_label_new("About"); wAbout=createPageAbout(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), wAbout, pagesLabel); /* Bottom buttons */ buttonBox=gtk_hbutton_box_new(); gtk_container_set_border_width(GTK_CONTAINER(buttonBox), 5); gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox),GTK_BUTTONBOX_END); quitButton=gtk_button_new_with_label("Quit"); g_signal_connect_swapped(G_OBJECT(quitButton), "clicked", G_CALLBACK(onQuitButton), NULL); gtk_container_add(GTK_CONTAINER(buttonBox), quitButton); gtk_box_pack_start(GTK_BOX(mainVBox), buttonBox, FALSE, FALSE, 0); /* Status Bar */ statusBar=gtk_statusbar_new(); gtk_box_pack_start(GTK_BOX(mainVBox), statusBar, FALSE, FALSE, 0); gtk_statusbar_push(GTK_STATUSBAR(statusBar), 0, "Welcome"); gtk_widget_show_all(window); gtk_main(); return 0; } void onQuitButton(GtkWidget *widget, gpointer data) { extern bool wm_auto_update; if(wm_update) { GtkWidget *msgDialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Update the wiimote before leaving ?"); if(gtk_dialog_run(GTK_DIALOG(msgDialog)) == GTK_RESPONSE_YES) wm_auto_update=TRUE; gtk_widget_destroy(msgDialog); } gtk_main_quit(); } void updateStatusBar(char *msg){ gtk_statusbar_pop(GTK_STATUSBAR(statusBar), 0); gtk_statusbar_push(GTK_STATUSBAR(statusBar), 0, msg); } transfermii-0.6.1/LICENSE0000644000175200017540000003542210751645145014420 0ustar shinboshinbo GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS transfermii-0.6.1/Makefile.old0000644000175200017540000000246010751657000015615 0ustar shinboshinbo#Copyright (C) 2007-2008 Arnaud Ysmal MAKEFILE=Makefile.old CC=gcc CFLAGS=-Wall -Werror LIBCWIID_NAME=cwiid LIBCWIID_DIR=cwiid LIBCWIID=$(LIBCWIID_DIR)/lib$(LIBCWIID_NAME).a LIBTMII_NAME=tmii LIBTMII_DIR=tmii LIBTMII=$(LIBTMII_DIR)/lib$(LIBTMII_NAME).a LDOPTS=-lbluetooth -lpthread -lrt -L$(LIBCWIID_DIR) -L$(LIBTMII_DIR) -l$(LIBCWIID_NAME) -l$(LIBTMII_NAME) SRCS=transfermii_cli.c OBJS=$(SRCS:.c=.o) BIN=transfermii_cli GUIBIN=transfermii_gui GUIDIR=gui prefix=/usr/local bindir=$(prefix)/bin all : $(BIN) $(GUIBIN) cli : $(BIN) $(BIN) : $(OBJS) $(LIBCWIID) $(LIBTMII) $(CC) -o $@ $^ $(LDOPTS) gui: $(GUIBIN) $(GUIBIN) : $(LIBCWIID) $(LIBTMII) @(cd $(GUIDIR) && $(MAKE) -f $(MAKEFILE)) $(LIBTMII) : @(cd $(LIBTMII_DIR) && $(MAKE) -f $(MAKEFILE)) $(LIBCWIID) : @(cd $(LIBCWIID_DIR) && $(MAKE) -f $(MAKEFILE)) %.o : %.c $(CC) -o $@ -c $< $(CFLAGS) install : $(BIN) cp $(BIN) $(bindir) uninstall : -rm $(bindir)/$(BIN) .PHONY : clean mrproper clean : -rm $(OBJS) $(BIN) @(cd $(LIBTMII_DIR) && $(MAKE) clean -f $(MAKEFILE)) @(cd $(LIBCWIID_DIR) && $(MAKE) clean -f $(MAKEFILE)) @(cd $(GUIDIR) && $(MAKE) clean -f $(MAKEFILE)) mrproper : clean -rm -rf $(BIN) @(cd $(LIBTMII_DIR) && $(MAKE) mrproper -f $(MAKEFILE)) @(cd $(LIBCWIID_DIR) && $(MAKE) mrproper -f $(MAKEFILE)) transfermii-0.6.1/README0000644000175200017540000000251410751651611014262 0ustar shinboshinboCopyright (C) 2007-2008 Arnaud Ysmal 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------- TransferMii : (http://transfermii.stacktic.org) -------------------------------------------------------------------------- Transfer mii from and to a Nintendo wiimote REQUIREMENTS bluetooth support gtk-2.0 for the GUI transfermii_cli : To compile it : --- with cmake : cmake . && make transfermii_cli --- without cmake : make -f Makefile.old cli transfermii_gui : To compile it : --- with cmake : cmake . && make transfermii_gui --- without cmake : make -f Makefile.old gui Feel free to send your comments to transfermii-0.6.1/tmii/0000755000175200017540000000000010763524036014345 5ustar shinboshinbotransfermii-0.6.1/tmii/CMakeLists.txt0000644000175200017540000000011510751645221017077 0ustar shinboshinboADD_LIBRARY(tmii filefunctions.c miifunctions.c others.c wiimotefunctions.c) transfermii-0.6.1/tmii/filefunctions.c0000644000175200017540000000544110763451333017364 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * filefunctions.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include "tmii.h" extern bool wm_read; /* Reads mii from miifile */ bool fileRead(char *miifile) { FILE *fd; struct stat filestat; if (stat(miifile, &filestat)) { fprintf(stderr, "%s : file reading error\n", miifile); return FALSE; } if (filestat.st_size != MII_SIZE) { fprintf(stderr, "%s : incorrect mii file\n", miifile); return FALSE; } printf("Reading mii from file %s...\n", miifile); if ((fd = fopen(miifile, "r"))) { if (fread(mii, MII_SIZE, 1, fd) != 1) { fprintf(stderr, "Can't read %s\n", miifile); fclose(fd); return FALSE; } fclose(fd); } else { fprintf(stderr, "Can't open %s\n", miifile); return FALSE; } return TRUE; } /* Writes mii to miifile */ /* Slot 0 : writes mii array */ /* Slot 1-10 : writes corresponding mii from miiblock */ bool fileWrite(char *miifile, int slot) { FILE *fd; unsigned char *pmii; if (slot < 0 || slot > 10) { fprintf(stderr, "incorrect slot, must be between 0 and 10\n"); return FALSE; } if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; pmii = miiAddress(slot); } else { pmii = mii; } if (!*(int*)pmii) { fprintf(stderr, "mii or slot empty\n"); return FALSE; } printf("Writing file %s...\n", miifile); if ((fd = fopen(miifile, "w"))) { if (fwrite(pmii, MII_SIZE, 1, fd) != 1) { fprintf(stderr, "Can't write %s\n", miifile); fclose(fd); return FALSE; } fclose(fd); } else { fprintf(stderr, "Can't open %s\n", miifile); return FALSE; } return TRUE; } /* Displays information on miifile */ bool fileInfo(char *miifile) { char name[MII_NAME_LENGTH_CHAR+1]; if (!fileRead(miifile)) return FALSE; getMiiNameAscii(name, 0); printf("Mii's name : %s\t", name); getMiiCreatorAscii(name, 0); printf("Creator : %s\t", name); printf("Sex : %s\n", (getMiiSex(0)=='F')?"Female":"Male"); return TRUE; } transfermii-0.6.1/tmii/Makefile.old0000644000175200017540000000061110751651511016554 0ustar shinboshinbo#Copyright (C) 2007-2008 Arnaud Ysmal CC=gcc CFLAGS=-Wall -Werror SRCS=filefunctions.c wiimotefunctions.c others.c miifunctions.c LIBNAME=libtmii.a OBJS= $(SRCS:.c=.o) all : $(LIBNAME) $(LIBNAME) : $(OBJS) ar rc $(LIBNAME) $^ ranlib $(LIBNAME) %.o: %.c $(CC) -o $@ -c $< $(CFLAGS) .PHONY: clean mrproper clean: rm -rf $(OBJS) mrproper: clean rm -rf $(LIBNAME) transfermii-0.6.1/tmii/miifunctions.c0000644000175200017540000002015210763522436017222 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * miifunctions.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include "tmii.h" #define MII_CREATOR 0 #define MII_NAME 1 extern bool wm_read; extern bool wm_update; bool big_endian = 0; unsigned char mii[MII_SIZE]; unsigned char miiblock[BLOCK_SIZE]; unsigned char wii_mac[3]; /* *miibuf must have a size of MII_SIZE */ /* if miibuf is NULL the mii is copied to the mii array */ bool getMii(unsigned char *miibuf, int slot) { if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (!wm_read && !wiimoteRead()) return FALSE; memcpy(miibuf?miibuf:mii, miiAddress(slot), MII_SIZE); return TRUE; } static bool getMiiString(uint16_t *str, int slot, bool name) { unsigned char *src; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (!str) { fprintf(stderr, "null pointer\n"); return FALSE; } if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; src = miiAddress(slot)+(name?MII_NAME_OFFSET:MII_CREATOR_OFFSET); } else { src = mii+(name?MII_NAME_OFFSET:MII_CREATOR_OFFSET); } return !memcpy(str, src, MII_CREATOR_LENGTH_BYTE); } static bool setMiiString(uint16_t *str, int slot, bool name) { unsigned char *dest; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (!str) { fprintf(stderr, "null poiter\n"); return FALSE; } if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; dest = miiAddress(slot)+(name?MII_NAME_OFFSET:MII_CREATOR_OFFSET); } else { dest = mii+(name?MII_NAME_OFFSET:MII_CREATOR_OFFSET); } return !memcpy(dest, str, MII_CREATOR_LENGTH_BYTE); } /* *creatorsname must have a size of MII_CREATOR_LENGTH_BYTE+1 */ bool getMiiCreator(uint16_t *creatorsname, int slot) { int i = 1; big_endian=!*(char*)&i; getMiiString(creatorsname, slot, MII_CREATOR); if (!big_endian) { for (i=0; i10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; return (*miiAddress(slot)&0x40)?'F':'M'; } else { return (*mii&0x40)?'F':'M'; } } bool setMiiSex(char sex, int slot) { unsigned char *pmii; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (sex!='F' && sex!='M') { fprintf(stderr, "Sex inccorrect\n"); return FALSE; } if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; pmii=miiAddress(slot); } else { pmii=mii; } if (sex=='F' && !(*pmii&0x40)) *pmii|=0x40; else if (sex=='M' && *pmii&0x40) *pmii^=0x40; return TRUE; } /* Lists mii on the wiimote */ bool listMiis() { char name[MII_NAME_LENGTH_CHAR]; int i; if (!wm_read && !wiimoteRead()) return FALSE; for (i=1; i<=MII_NB; i++) { printf("Slot %i\t", i); if (miiIsEmpty(i)) { printf("empty\n"); continue; } getMiiNameAscii(name, i); printf("Name : %s\t", name); getMiiCreatorAscii(name, i); printf("Creator : %s\t", name); printf("Sex : %s\n", (getMiiSex(i)=='F')?"Female":"Male"); } return TRUE; } /* Sets the new mac address */ /* slot 0 : updates mac address of the mii array */ /* slot 1-10 : updates corresponding mii on miiblock array */ bool setMacAddress(int slot) { unsigned char* pmac; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (!*(short*)wii_mac) return TRUE; if (slot) { if (!wm_read && !wiimoteRead()) return FALSE; pmac = miiAddress(slot)+MAC_OFFSET; wm_update=TRUE; } else { pmac=mii+MAC_OFFSET; } if (*pmac != MAC_SUM) { printf("Macsum incorrect, Correcting...\n"); *pmac=MAC_SUM; } pmac[1] = wii_mac[0]; pmac[2] = wii_mac[1]; pmac[3] = wii_mac[2]; return TRUE; } bool getMiiMacAddress(unsigned char *macaddr, int slot) { unsigned char *pmac; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } pmac = (slot?miiAddress(slot):mii)+MAC_OFFSET; macaddr[0] = *(++pmac); macaddr[1] = *(++pmac); macaddr[2] = *(++pmac); return TRUE; } /* Adds mii */ /* Slot 0 : looks for the first empty slot */ bool addMii(char* miifile, int slot) { unsigned char* pmii; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } if (!fileRead(miifile) || (!wm_read && !wiimoteRead())) return FALSE; if (slot==0 && !(slot=nextEmptySlot())) { fprintf(stderr, "No empty slot\n"); return FALSE; } pmii = miiAddress(slot); if (!miiIsEmpty(slot)) { printf("Slot is not empty, overwrite ? (y/n) : "); if (getchar() != 'y') return FALSE; } printf("Adding mii from %s to slot %i...\n", miifile, slot); if (!memcpy(pmii, mii, MII_SIZE)) { fprintf(stderr, "Adding mii to miiblock error\n"); return FALSE; } miiblock[4] = 0; miiblock[5] = 0; return wm_update=TRUE; } bool delMii(int slot) { unsigned char *pmii; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } pmii = slot?miiAddress(slot):mii; memset(pmii, 0, MII_SIZE); return TRUE; } bool miiIsEmpty(int slot) { if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } return !((slot&&*(int*)miiAddress(slot))||(!slot&&*(int*)mii)); } bool miiSeemsValid(int slot) { unsigned char *pmii; if (slot<0 || slot>10) { fprintf(stderr, "Slot incorrect\n"); return FALSE; } pmii = slot?miiAddress(slot):mii; if (*pmii&0x80) { fprintf(stderr, "invalid bit is set\n"); return FALSE; } if (*(pmii+=MII_NAME_OFFSET+MII_NAME_LENGTH_BYTE) > 0x7F) { fprintf(stderr, "height error\n"); return FALSE; } if (*(++pmii) > 0x7F) { fprintf(stderr, "weight error\n"); return FALSE; } return TRUE; } transfermii-0.6.1/tmii/others.c0000644000175200017540000000760510751650375016030 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * others.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include "tmii.h" extern char wm_read; extern char wm_update; extern unsigned char wii_mac[3]; /* Checks and corrects crc */ void crcCheck() { int byteidx, bitidx, crc=0, i; if (!wm_read && !wiimoteRead()) return; printf("Checking crc...\n"); for (byteidx=0; byteidx=0; bitidx--) crc = (((crc<<1)|((miiblock[byteidx]>>bitidx)&0x1))^ (((crc&0x8000)!=0)?0x1021:0)); for (i=16; i>0; i--) crc = ((crc << 1) ^ (((crc & 0x8000) != 0) ? 0x1021 : 0)); if ((crc & 0xffff) != ((miiblock[BLOCK_SIZE-2]<<8)|(miiblock[BLOCK_SIZE-1]))) { printf("wrong crc !\nCorrecting...\n"); miiblock[BLOCK_SIZE-2] = (crc>>8)&0xFF; miiblock[BLOCK_SIZE-1] = crc&0xFF; wm_update = TRUE; printf("Corrected !\n"); } else { printf("crc is correct !\n"); } } /* string(XX:XX:XX) to unsigned char[3] */ char parseMacAddress(char *macaddr) { if (macaddr==NULL || macaddr[2]!=':' || macaddr[5]!=':' || macaddr[8]!='\0') return FALSE; if (macaddr[0] >= '0' && macaddr[0] <= '9') { wii_mac[0] = (macaddr[0]-'0')<<4; } else if ((macaddr[0]&0xDF) >= 'A' && (macaddr[0]&0xDF)<='F') { wii_mac[0] = ((macaddr[0]&0xDF)-'A'+10)<<4; } else { wii_mac[0] = 0; return FALSE; } if (macaddr[1] >= '0' && macaddr[1] <= '9') { wii_mac[0] += (macaddr[1]-'0'); } else if ((macaddr[1]&0xDF) >= 'A' && (macaddr[1]&0xDF)<='F') { wii_mac[0] += ((macaddr[1]&0xDF)-'A'+10); } else { wii_mac[0] = 0; return FALSE; } if (macaddr[3] >= '0' && macaddr[3] <= '9') { wii_mac[1] = (macaddr[3]-'0')<<4; } else if ((macaddr[3]&0xDF) >= 'A' && (macaddr[3]&0xDF)<='F') { wii_mac[1] = ((macaddr[3]&0xDF)-'A'+10)<<4; } else { wii_mac[0] = 0; wii_mac[1] = 0; return FALSE; } if (macaddr[4] >= '0' && macaddr[4] <= '9') { wii_mac[1] += (macaddr[4]-'0'); } else if ((macaddr[4]&0xDF) >= 'A' && (macaddr[4]&0xDF)<='F') { wii_mac[1] += ((macaddr[4]&0xDF)-'A'+10); } else { wii_mac[0] = 0; wii_mac[1] = 0; return FALSE; } if (macaddr[6] >= '0' && macaddr[6] <= '9') { wii_mac[2] = (macaddr[6]-'0')<<4; } else if ((macaddr[6]&0xDF) >= 'A' && (macaddr[6]&0xDF)<='F') { wii_mac[2] = ((macaddr[6]&0xDF)-'A'+10)<<4; } else { wii_mac[0] = 0; wii_mac[1] = 0; wii_mac[2] = 0; return FALSE; } if (macaddr[7] >= '0' && macaddr[7] <= '9') { wii_mac[2] += (macaddr[7]-'0'); } else if ((macaddr[7]&0xDF) >= 'A' && (macaddr[7]&0xDF)<='F') { wii_mac[2] += ((macaddr[7]&0xDF)-'A'+10); } else { wii_mac[0] = 0; wii_mac[1] = 0; wii_mac[2] = 0; return FALSE; } return TRUE; } void beu16toascii(uint16_t *src, char *dest) { char *tmp = (char*)src; dest[0] = tmp[1]; dest[1] = tmp[3]; dest[2] = tmp[5]; dest[3] = tmp[7]; dest[4] = tmp[9]; dest[5] = tmp[11]; dest[6] = tmp[13]; dest[7] = tmp[15]; dest[8] = tmp[17]; dest[9] = tmp[19]; } void asciitobeu16(char *src, uint16_t *dest) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest[3] = src[3]; dest[4] = src[4]; dest[5] = src[5]; dest[6] = src[6]; dest[7] = src[7]; dest[8] = src[8]; dest[9] = src[9]; } transfermii-0.6.1/tmii/tmii.h0000644000175200017540000000577510763444436015503 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * tmii.h (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef _TMII_H #define _TMII_H #include #define FIRST_BLOCK (0x0fca) #define SECOND_BLOCK (0x12ba) #define BLOCK_SIZE (0x2f0) #define FIRST_MII (0x8) #define MII_SIZE (0x4a) #define MII_NB (0xa) #define MII_NAME_LENGTH_CHAR (0xa) #define MII_NAME_LENGTH_BYTE (0x14) #define MII_NAME_OFFSET (0x2) #define MII_CREATOR_LENGTH_CHAR (0xa) #define MII_CREATOR_LENGTH_BYTE (0x14) #define MII_CREATOR_OFFSET (0x36) #define MII_ID_OFFSET (0x18) #define MAC_OFFSET (0x1c) #define MAC_SUM (0xc2) #ifndef TRUE #define TRUE (1) #define FALSE (0) #define swap16(x) ((((x)&0xFF00)>>8) | (((x)&0xFF)<<8)) #endif #define miiAddress(n) (miiblock+FIRST_MII+((n-1)*MII_SIZE)) typedef char bool; /* filefunctions */ bool fileRead(char *miifile); bool fileWrite(char *miifile, int slot); bool fileInfo(char *miifile); /* others */ bool parseMacAddress(char* macaddr); void crcCheck(void); void beu16toascii(uint16_t *src, char *dest); void asciitobeu16(char *src, uint16_t *dest); /* wiimotefunctions */ bool wiimoteRead(void); bool wiimoteWrite(void); int nextEmptySlot(void); void wiimoteDisconnect(void); bool wiimoteConnect(void); /* miifunctions */ bool getMii(unsigned char *miibuf, int slot); bool getMiiCreator(uint16_t *creatorsname, int slot); bool setMiiCreator(uint16_t *creatorsname, int slot); bool getMiiCreatorAscii(char *creatorsname, int slot); bool setMiiCreatorAscii(char *creatorsname, int slot); bool getMiiName(uint16_t *miisname, int slot); bool setMiiName(uint16_t *miisname, int slot); bool getMiiNameAscii(char *miisname, int slot); bool setMiiNameAscii(char *miisname, int slot); char getMiiSex(int slot); bool setMiiSex(char sex, int slot); bool listMiis(void); bool addMii(char* miifile, int slot); bool delMii(int slot); bool setMacAddress(int slot); bool miiIsEmpty(int slot); bool miiSeemsValid(int slot); bool getMiiMacAddress(unsigned char *macaddr, int slot); bool setCreatorName(char *creatorsname, int slot); bool setMiiName(uint16_t *miisname, int slot); bool correctMiiIds(void); extern unsigned char mii[MII_SIZE]; extern unsigned char miiblock[BLOCK_SIZE]; extern bool wm_auto_update; extern bool wm_read; extern bool wm_connected; extern bool wm_update; extern bdaddr_t ba; #endif transfermii-0.6.1/tmii/wiimotefunctions.c0000644000175200017540000000525410763523333020124 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * wiimotefunctions.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #ifdef CWIID_STATIC #include "../cwiid/cwiid.h" #else #include #endif #include "tmii.h" extern unsigned char miiblock[BLOCK_SIZE]; bool wm_update = FALSE; bool wm_read = FALSE; bool wm_connected = FALSE; bool wm_auto_update = FALSE; cwiid_wiimote_t *wm; bdaddr_t ba = *BDADDR_ANY; cwiid_mesg_callback_t *callback; /* Disconnects the wiimote (called by wconnect() by atexit)*/ void wiimoteDisconnect() { if (!wm_connected) return; if (wm_auto_update && wm_update) wiimoteWrite(); printf("Disconnecting...\n"); wm_connected=cwiid_close(wm); wm_read = wm_update = FALSE; } /* Looks for a wiimote */ bool wiimoteConnect() { if (wm_connected) return TRUE; printf("Looking for a wiimote... (please press 1+2 on the wiimote)\n"); if (!(wm = cwiid_open(&ba, CWIID_FLAG_MESG_IFC))) return FALSE; cwiid_set_led(wm, CWIID_LED1_ON|CWIID_LED4_ON); atexit(wiimoteDisconnect); return (wm_connected=TRUE); } /* Fills miiblock with mii block from wiimote EEPROM */ bool wiimoteRead() { if (!wm_connected && !wiimoteConnect()) return FALSE; printf("Reading block from the wiimote...\n"); if (wm_read) return TRUE; return wm_read=(!cwiid_read(wm, CWIID_RW_EEPROM, FIRST_BLOCK, BLOCK_SIZE, miiblock)); } /* Writes miiblock to wiimote EEPROM */ bool wiimoteWrite() { if (!wm_update) return TRUE; if (!wm_connected && !wiimoteConnect()) return FALSE; crcCheck(); printf("Writing block to the wiimote EEPROM...\n"); wm_update = FALSE; return !(cwiid_write(wm, CWIID_RW_EEPROM, FIRST_BLOCK, BLOCK_SIZE, miiblock) || cwiid_write(wm, CWIID_RW_EEPROM, SECOND_BLOCK, BLOCK_SIZE, miiblock)); } /* Looks for an empty slot */ int nextEmptySlot() { int i; if (!wm_read && !wiimoteRead()) return FALSE; for (i=1; i<=MII_NB && !miiIsEmpty(i); i++) ; return i>MII_NB?0:i; } transfermii-0.6.1/transfermii_cli.c0000644000175200017540000000730610751650626016731 0ustar shinboshinbo/* * Copyright (C) 2007-2008 Arnaud Ysmal * * transfermii_cli.c (TransferMii) * * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include "tmii/tmii.h" #define OPT_UL 0x1 #define OPT_DL (OPT_UL+1) #define OPT_LS (OPT_DL+1) #define OPT_FI (OPT_LS+1) static void help(const char *name) { printf("Usage : %s OPTION [FILE [FILE]]\n", name); printf(" -b\t Specify bluetooth device (%s -b XX:XX:XX:XX:XX:XX" " ...)\n", name); printf(" -d\t Download miis from wiimote (%s -d [-s begin [-t end]]" ")\n \t -s\t slot or first slot to download " "(default 1)\n" " \t -t\t last slot to download (default 10)\n", name); printf(" -h\t Show this message\n"); printf(" -i\t Display creator and mii's name of miifile (%s -i" " miifile [FILE...])\n", name); printf(" -l\t List all miis on the wiimote\n"); printf(" -m\t Set the wii mac address (3 last bytes) (%s -m XX:XX:XX " "...)\n", name); printf(" -u\t Upload miis to wiimote\n" " \t (%s -u filename [-s slot] [FILE])\n" " \t FILE : mii files to upload to the next empty slot " "if possible\n", name); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { char *filename; char option = 0, fname[11] = "slot0X.mii"; int arg, slot = 0, slot2 = 0, i; extern char *optarg; extern int optind; extern bdaddr_t ba; if (argc == 1) help(*argv); while ((arg=getopt(argc, argv, "b:dhi:lm:s:t:u:")) != EOF) { switch (arg) { case 'b' : str2ba(optarg, &ba); break; case 'd' : if (option) help(*argv); option = OPT_DL; break; case 'h' : help(*argv); break; case 'i' : if (option) help(*argv); option = OPT_FI; filename = optarg; break; case 'l' : if (option) help(*argv); option = OPT_LS; break; case 'm' : parseMacAddress(optarg); break; case 's' : if (!slot) slot=atoi(optarg); break; case 't' : if (!slot2) slot2=atoi(optarg); break; case 'u' : if (option) help(*argv); option = OPT_UL; filename = optarg; break; default : help(*argv); } } switch (option) { case OPT_FI : fileInfo(filename); for (i=optind; i10 || slot2<1 || slot2>10) { fprintf(stderr, "slot must be between 1 and 10\n"); exit(EXIT_FAILURE); } for (; slot<=slot2 && slot<=MII_NB; slot++) { if (slot<10) { fname[5]=slot+'0'; } else { fname[4]='1'; fname[5]='0'; } fileWrite(fname, slot); } break; case OPT_LS : listMiis(); break; case OPT_UL : wm_auto_update=TRUE; addMii(filename, slot); if (optind>argc) exit(EXIT_SUCCESS); for (i=optind; i