/* gc_n64_usb : Gamecube or N64 controller to USB firmware Copyright (C) 2007-2016 Raphael Assenat 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 3 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, see . */ #include #include #include "requests.h" #include "config.h" #include "hiddata.h" #include "usbpad.h" #include "bootloader.h" #include "gcn64_protocol.h" #include "version.h" #include "main.h" // dataHidReport is 40 bytes. #define CMDBUF_SIZE 41 #define STATE_IDLE 0 #define STATE_NEW_COMMAND 1 // New command in buffer #define STATE_COMMAND_DONE 2 // Result in buffer //#define DEBUG extern char g_polling_suspended; static volatile uint8_t state = STATE_IDLE; static unsigned char cmdbuf[CMDBUF_SIZE]; static volatile unsigned char cmdbuf_len = 0; /*** Get/Set report called from interrupt context! */ uint16_t hiddata_get_report(void *ctx, struct usb_request *rq, const uint8_t **dat) { // printf("Get data\n"); if (state == STATE_COMMAND_DONE) { *dat = cmdbuf; state = STATE_IDLE; #ifdef DEBUG printf_P(PSTR("hiddata idle, sent %d bytes\r\n"), cmdbuf_len); #endif return cmdbuf_len; } return 0; } /*** Get/Set report called from interrupt context! */ uint8_t hiddata_set_report(void *ctx, const struct usb_request *rq, const uint8_t *dat, uint16_t len) { #ifdef DEBUG int i; printf_P(PSTR("Set data %d\n"), len); for (i=0; isuspendPolling) { ops->suspendPolling(cmdbuf[1]); } break; case RQ_GCN64_GET_VERSION: // CMD: RQ // Answer: RQ, version string (zero-terminated) strcpy((char*)(cmdbuf + 1), g_version); cmdbuf_len = 1 + strlen(g_version) + 1; break; case RQ_GCN64_GET_SIGNATURE: strcpy_P((char*)(cmdbuf + 1), g_signature); cmdbuf_len = 1 + strlen_P(g_signature) + 1; break; case RQ_GCN64_GET_CONTROLLER_TYPE: // CMD : RQ, CHN // Answer: RQ, CHN, TYPE cmdbuf[2] = current_pad_type; cmdbuf_len = 3; break; case RQ_GCN64_SET_VIBRATION: // CMD : RQ, CHN, Vibrate // Answer: RQ, CHN, Vibrate if (ops && ops->forceVibration) { ops->forceVibration(cmdbuf[1], cmdbuf[2]); } cmdbuf_len = 3; break; } #ifdef DEBUG printf("Pending data %d\n", cmdbuf_len); for (i=0; i