mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2024-12-21 23:08:53 -05:00
Move more logic from main to usbpad, implement serial from eeprom
This commit is contained in:
parent
5818aa2175
commit
54196a0d76
@ -1 +1 @@
|
||||
OBJS=main.o usb.o usbpad.o mappings.o gcn64_protocol.o n64.o gamecube.o usart1.o bootloader.o eeprom.o config.o hiddata.o
|
||||
OBJS=main.o usb.o usbpad.o mappings.o gcn64_protocol.o n64.o gamecube.o usart1.o bootloader.o eeprom.o config.o hiddata.o usbstrings.o
|
||||
|
282
main.c
282
main.c
@ -17,21 +17,13 @@
|
||||
#include "usbpad.h"
|
||||
#include "eeprom.h"
|
||||
#include "hiddata.h"
|
||||
#include "usbstrings.h"
|
||||
|
||||
uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat);
|
||||
uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
|
||||
|
||||
uint16_t hid_get_report_data(struct usb_request *rq, const uint8_t **dat);
|
||||
uint8_t hid_set_report_data(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
|
||||
|
||||
/* Those .c files are included rather than linked for we
|
||||
* want the sizeof() operator to work on the arrays */
|
||||
#include "reportdesc.c"
|
||||
#include "dataHidReport.c"
|
||||
|
||||
const wchar_t *const g_usb_strings[] = {
|
||||
[0] = L"raphnet technologies", // 1 : Vendor
|
||||
[1] = L"GC/N64 to USB v3.0", // 2: Product
|
||||
[2] = L"123456", // 3 : Serial
|
||||
};
|
||||
|
||||
struct cfg0 {
|
||||
struct usb_configuration_descriptor configdesc;
|
||||
@ -141,7 +133,7 @@ static struct usb_parameters usb_params = {
|
||||
.devdesc = (PGM_VOID_P)&device_descriptor,
|
||||
.configdesc = (PGM_VOID_P)&cfg0,
|
||||
.configdesc_ttllen = sizeof(cfg0),
|
||||
.num_strings = ARRAY_SIZE(g_usb_strings),
|
||||
.num_strings = NUM_USB_STRINGS,
|
||||
.strings = g_usb_strings,
|
||||
|
||||
.n_hid_interfaces = 2,
|
||||
@ -149,8 +141,8 @@ static struct usb_parameters usb_params = {
|
||||
[0] = {
|
||||
.reportdesc = gcn64_usbHidReportDescriptor,
|
||||
.reportdesc_len = sizeof(gcn64_usbHidReportDescriptor),
|
||||
.getReport = hid_get_report_main,
|
||||
.setReport = hid_set_report_main,
|
||||
.getReport = usbpad_hid_get_report,
|
||||
.setReport = usbpad_hid_set_report,
|
||||
},
|
||||
[1] = {
|
||||
.reportdesc = dataHidReport,
|
||||
@ -213,240 +205,6 @@ void hwinit(void)
|
||||
PRR1 = 0;
|
||||
}
|
||||
|
||||
static unsigned char hid_report_data[32];
|
||||
static unsigned char gamepad_report0[32];
|
||||
|
||||
// Output Report IDs for various functions
|
||||
#define REPORT_SET_EFFECT 0x01
|
||||
#define REPORT_SET_STATUS 0x02
|
||||
#define REPORT_SET_PERIODIC 0x04
|
||||
#define REPORT_SET_CONSTANT_FORCE 0x05
|
||||
#define REPORT_EFFECT_OPERATION 0x0A
|
||||
#define REPORT_EFFECT_BLOCK_IDX 0x0B
|
||||
#define REPORT_DISABLE_ACTUATORS 0x0C
|
||||
#define REPORT_PID_POOL 0x0D
|
||||
|
||||
// Feature reports
|
||||
#define REPORT_CREATE_EFFECT 0x09
|
||||
|
||||
// For the 'Usage Effect Operation' report
|
||||
#define EFFECT_OP_START 1
|
||||
#define EFFECT_OP_START_SOLO 2
|
||||
#define EFFECT_OP_STOP 3
|
||||
|
||||
// Feature report
|
||||
#define PID_SIMULTANEOUS_MAX 3
|
||||
#define PID_BLOCK_LOAD_REPORT 2
|
||||
|
||||
static volatile unsigned char gamepad_vibrate = 0; // output
|
||||
|
||||
static unsigned char vibration_on = 0;
|
||||
static unsigned char constant_force = 0;
|
||||
static unsigned char magnitude = 0;
|
||||
|
||||
static unsigned char _FFB_effect_index;
|
||||
#define LOOP_MAX 0xFFFF
|
||||
static unsigned int _loop_count;
|
||||
|
||||
static void decideVibration(void)
|
||||
{
|
||||
if (!vibration_on) {
|
||||
gamepad_vibrate = 0;
|
||||
} else {
|
||||
if (constant_force > 0x7f) {
|
||||
gamepad_vibrate = 1;
|
||||
}
|
||||
if (magnitude > 0x7f) {
|
||||
gamepad_vibrate = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat)
|
||||
{
|
||||
uint8_t report_id = (rq->wValue & 0xff);
|
||||
|
||||
// USB HID 1.11 section 7.2.1 Get_Report
|
||||
// wValue high byte : report type
|
||||
// wValue low byte : report id
|
||||
// wIndex Interface
|
||||
switch (rq->wValue >> 8)
|
||||
{
|
||||
case HID_REPORT_TYPE_INPUT:
|
||||
{
|
||||
if (report_id == 1) { // Joystick
|
||||
// report_id = rq->wValue & 0xff
|
||||
// interface = rq->wIndex
|
||||
*dat = gamepad_report0;
|
||||
printf_P(PSTR("Get joy report\r\n"));
|
||||
return 9;
|
||||
} else if (report_id == 2) { // 2 : ES playing
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 0;
|
||||
hid_report_data[2] = _FFB_effect_index;
|
||||
printf_P(PSTR("ES playing\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 3;
|
||||
} else {
|
||||
printf_P(PSTR("Get input report %d ??\r\n"), rq->wValue & 0xff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REPORT_TYPE_FEATURE:
|
||||
if (report_id == PID_BLOCK_LOAD_REPORT) {
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 0x1; // Effect block index
|
||||
hid_report_data[2] = 0x1; // (1: success, 2: oom, 3: load error)
|
||||
hid_report_data[3] = 10;
|
||||
hid_report_data[4] = 10;
|
||||
printf_P(PSTR("block load\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 5;
|
||||
}
|
||||
else if (report_id == PID_SIMULTANEOUS_MAX) {
|
||||
hid_report_data[0] = report_id;
|
||||
// ROM Effect Block count
|
||||
hid_report_data[1] = 0x1;
|
||||
hid_report_data[2] = 0x1;
|
||||
// PID pool move report?
|
||||
hid_report_data[3] = 0xff;
|
||||
hid_report_data[4] = 1;
|
||||
printf_P(PSTR("simultaneous max\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 5;
|
||||
}
|
||||
else if (report_id == REPORT_CREATE_EFFECT) {
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 1;
|
||||
printf_P(PSTR("create effect\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 2;
|
||||
} else {
|
||||
printf_P(PSTR("Unknown feature %d\r\n"), rq->wValue & 0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
printf_P(PSTR("Unhandled hid get report type=0x%02x, rq=0x%02x, wVal=0x%04x, wLen=0x%04x\r\n"), rq->bmRequestType, rq->bRequest, rq->wValue, rq->wLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (len < 1) {
|
||||
printf_P(PSTR("shrt\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rq->wValue >> 8) == HID_REPORT_TYPE_OUTPUT) {
|
||||
|
||||
switch(data[0])
|
||||
{
|
||||
case REPORT_SET_STATUS:
|
||||
printf_P(PSTR("eff. set stat 0x%02x 0x%02x\r\n"),data[1],data[2]);
|
||||
break;
|
||||
case REPORT_EFFECT_BLOCK_IDX:
|
||||
printf_P(PSTR("eff. blk. idx %d\r\n"), data[1]);
|
||||
break;
|
||||
case REPORT_DISABLE_ACTUATORS:
|
||||
printf_P(PSTR("disable actuators\r\n"));
|
||||
break;
|
||||
case REPORT_PID_POOL:
|
||||
printf_P(PSTR("pid pool\r\n"));
|
||||
break;
|
||||
case REPORT_SET_EFFECT:
|
||||
_FFB_effect_index = data[1];
|
||||
printf_P(PSTR("set effect %d\n"), data[1]);
|
||||
break;
|
||||
case REPORT_SET_PERIODIC:
|
||||
magnitude = data[2];
|
||||
// decideVibration();
|
||||
printf_P(PSTR("periodic mag: %d"), data[2]);
|
||||
break;
|
||||
case REPORT_SET_CONSTANT_FORCE:
|
||||
if (data[1] == 1) {
|
||||
constant_force = data[2];
|
||||
decideVibration();
|
||||
printf_P(PSTR("Constant force"));
|
||||
}
|
||||
break;
|
||||
case REPORT_EFFECT_OPERATION:
|
||||
if (len != 4)
|
||||
return -1;
|
||||
/* Byte 0 : report ID
|
||||
* Byte 1 : bit 7=rom flag, bits 6-0=effect block index
|
||||
* Byte 2 : Effect operation
|
||||
* Byte 3 : Loop count */
|
||||
_loop_count = data[3]<<3;
|
||||
|
||||
printf_P(PSTR("EFFECT OP: rom=%s, idx=0x%02x"), data[1] & 0x80 ? "Yes":"No", data[1] & 0x7F);
|
||||
|
||||
switch(data[1] & 0x7F) // Effect block index
|
||||
{
|
||||
case 1: // constant force
|
||||
case 3: // square
|
||||
case 4: // sine
|
||||
switch (data[2]) // effect operation
|
||||
{
|
||||
case EFFECT_OP_START:
|
||||
printf_P(PSTR("Start\r\n"));
|
||||
vibration_on = 1;
|
||||
decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_START_SOLO:
|
||||
printf_P(PSTR("Start solo\r\n"));
|
||||
vibration_on = 1;
|
||||
decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_STOP:
|
||||
printf_P(PSTR("Stop\r\n"));
|
||||
vibration_on = 0;
|
||||
decideVibration();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// TODO : should probably drop these from the descriptor since they are
|
||||
|
||||
case 2: // ramp
|
||||
case 5: // triangle
|
||||
case 6: // sawtooth up
|
||||
case 7: // sawtooth down
|
||||
case 8: // spring
|
||||
case 9: // damper
|
||||
case 10: // inertia
|
||||
case 11: // friction
|
||||
case 12: // custom force data
|
||||
printf_P(PSTR("Ununsed effect %d\n"), data[1] & 0x7F);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf_P(PSTR("Set output report 0x%02x\r\n"), data[0]);
|
||||
}
|
||||
}
|
||||
else if ((rq->wValue >> 8) == HID_REPORT_TYPE_FEATURE) {
|
||||
switch(data[0])
|
||||
{
|
||||
case REPORT_CREATE_EFFECT:
|
||||
_FFB_effect_index = data[1];
|
||||
printf_P(PSTR("create effect %d\n"), data[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf_P(PSTR("What?\n"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf_P(PSTR("impossible\n"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define NUM_PAD_TYPES 2
|
||||
|
||||
@ -475,7 +233,14 @@ Gamepad *detectPad(void)
|
||||
|
||||
void eeprom_app_ready(void)
|
||||
{
|
||||
// TODO : Set serial number from configured value
|
||||
static wchar_t serial_from_eeprom[SERIAL_NUM_LEN+1];
|
||||
int i;
|
||||
|
||||
for (i=0; i<SERIAL_NUM_LEN; i++) {
|
||||
serial_from_eeprom[i] = g_eeprom_data.cfg.serial[i];
|
||||
}
|
||||
serial_from_eeprom[i] = 0;
|
||||
g_usb_strings[USB_STRING_SERIAL_IDX] = serial_from_eeprom;
|
||||
}
|
||||
|
||||
char g_polling_suspended = 0;
|
||||
@ -492,13 +257,14 @@ int main(void)
|
||||
{
|
||||
Gamepad *pad = NULL;
|
||||
gamepad_data pad_data;
|
||||
unsigned char gamepad_vibrate = 0;
|
||||
|
||||
hwinit();
|
||||
usart1_init();
|
||||
eeprom_init();
|
||||
|
||||
/* Init the buffer with idle data */
|
||||
usbpad_buildReport(NULL, gamepad_report0);
|
||||
usbpad_update(NULL);
|
||||
|
||||
sei();
|
||||
usb_init(&usb_params);
|
||||
@ -524,8 +290,7 @@ int main(void)
|
||||
pollDelay();
|
||||
}
|
||||
|
||||
decideVibration();
|
||||
|
||||
gamepad_vibrate = usbpad_mustVibrate();
|
||||
if (last_v != gamepad_vibrate) {
|
||||
if (pad && pad->setVibration) {
|
||||
pad->setVibration(gamepad_vibrate);
|
||||
@ -537,17 +302,16 @@ int main(void)
|
||||
pad->update();
|
||||
|
||||
if (pad->changed()) {
|
||||
int report_size;
|
||||
|
||||
pad->getReport(&pad_data);
|
||||
usbpad_buildReport(&pad_data, gamepad_report0);
|
||||
report_size = usbpad_getReportSize();
|
||||
usb_interruptSend(gamepad_report0, report_size);
|
||||
usbpad_update(&pad_data);
|
||||
|
||||
usb_interruptSend(usbpad_getReportBuffer(), usbpad_getReportSize());
|
||||
}
|
||||
} else {
|
||||
/* Just make sure gamepad_report0 holds valid and
|
||||
* inactive data for the HID GET_REPORT request */
|
||||
usbpad_buildReport(NULL, gamepad_report0);
|
||||
/* Just make sure the gamepad state holds valid data
|
||||
* to appear inactive (no buttons and axes in neutral) */
|
||||
usbpad_update(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
253
usbpad.c
253
usbpad.c
@ -1,4 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "usb.h"
|
||||
#include "gamepads.h"
|
||||
#include "usbpad.h"
|
||||
#include "mappings.h"
|
||||
@ -6,10 +8,44 @@
|
||||
#define REPORT_ID 1
|
||||
#define REPORT_SIZE 15
|
||||
|
||||
// Output Report IDs for various functions
|
||||
#define REPORT_SET_EFFECT 0x01
|
||||
#define REPORT_SET_STATUS 0x02
|
||||
#define REPORT_SET_PERIODIC 0x04
|
||||
#define REPORT_SET_CONSTANT_FORCE 0x05
|
||||
#define REPORT_EFFECT_OPERATION 0x0A
|
||||
#define REPORT_EFFECT_BLOCK_IDX 0x0B
|
||||
#define REPORT_DISABLE_ACTUATORS 0x0C
|
||||
#define REPORT_PID_POOL 0x0D
|
||||
|
||||
// Feature reports
|
||||
#define REPORT_CREATE_EFFECT 0x09
|
||||
|
||||
// For the 'Usage Effect Operation' report
|
||||
#define EFFECT_OP_START 1
|
||||
#define EFFECT_OP_START_SOLO 2
|
||||
#define EFFECT_OP_STOP 3
|
||||
|
||||
// Feature report
|
||||
#define PID_SIMULTANEOUS_MAX 3
|
||||
#define PID_BLOCK_LOAD_REPORT 2
|
||||
|
||||
|
||||
|
||||
void usbpad_init(void)
|
||||
|
||||
static volatile unsigned char gamepad_vibrate = 0; // output
|
||||
static unsigned char vibration_on = 0;
|
||||
static unsigned char constant_force = 0;
|
||||
static unsigned char magnitude = 0;
|
||||
|
||||
static unsigned char _FFB_effect_index;
|
||||
#define LOOP_MAX 0xFFFF
|
||||
static unsigned int _loop_count;
|
||||
|
||||
static unsigned char gamepad_report0[32];
|
||||
static unsigned char hid_report_data[32];
|
||||
|
||||
void usbpad_init()
|
||||
{
|
||||
}
|
||||
|
||||
@ -132,22 +168,22 @@ static void buildReportFromN64(const n64_pad_data *n64_data, unsigned char dstbu
|
||||
btnsToReport(buttons, dstbuf+13);
|
||||
}
|
||||
|
||||
void usbpad_buildReport(const gamepad_data *pad_data, unsigned char dstbuf[REPORT_SIZE])
|
||||
void usbpad_update(const gamepad_data *pad_data)
|
||||
{
|
||||
/* Always start with an idle report. Specific report builders can just
|
||||
* simply ignore unused parts */
|
||||
buildIdleReport(dstbuf);
|
||||
buildIdleReport(gamepad_report0);
|
||||
|
||||
if (pad_data)
|
||||
{
|
||||
switch (pad_data->pad_type)
|
||||
{
|
||||
case PAD_TYPE_N64:
|
||||
buildReportFromN64(&pad_data->n64, dstbuf);
|
||||
buildReportFromN64(&pad_data->n64, gamepad_report0);
|
||||
break;
|
||||
|
||||
case PAD_TYPE_GAMECUBE:
|
||||
buildReportFromGC(&pad_data->gc, dstbuf);
|
||||
buildReportFromGC(&pad_data->gc, gamepad_report0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -156,3 +192,210 @@ void usbpad_buildReport(const gamepad_data *pad_data, unsigned char dstbuf[REPOR
|
||||
}
|
||||
}
|
||||
|
||||
char usbpad_mustVibrate(void)
|
||||
{
|
||||
if (!vibration_on) {
|
||||
gamepad_vibrate = 0;
|
||||
} else {
|
||||
if (constant_force > 0x7f) {
|
||||
gamepad_vibrate = 1;
|
||||
}
|
||||
if (magnitude > 0x7f) {
|
||||
gamepad_vibrate = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return gamepad_vibrate;
|
||||
}
|
||||
|
||||
unsigned char *usbpad_getReportBuffer(void)
|
||||
{
|
||||
return gamepad_report0;
|
||||
}
|
||||
|
||||
uint16_t usbpad_hid_get_report(struct usb_request *rq, const uint8_t **dat)
|
||||
{
|
||||
uint8_t report_id = (rq->wValue & 0xff);
|
||||
|
||||
// USB HID 1.11 section 7.2.1 Get_Report
|
||||
// wValue high byte : report type
|
||||
// wValue low byte : report id
|
||||
// wIndex Interface
|
||||
switch (rq->wValue >> 8)
|
||||
{
|
||||
case HID_REPORT_TYPE_INPUT:
|
||||
{
|
||||
if (report_id == 1) { // Joystick
|
||||
// report_id = rq->wValue & 0xff
|
||||
// interface = rq->wIndex
|
||||
*dat = gamepad_report0;
|
||||
printf_P(PSTR("Get joy report\r\n"));
|
||||
return 9;
|
||||
} else if (report_id == 2) { // 2 : ES playing
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 0;
|
||||
hid_report_data[2] = _FFB_effect_index;
|
||||
printf_P(PSTR("ES playing\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 3;
|
||||
} else {
|
||||
printf_P(PSTR("Get input report %d ??\r\n"), rq->wValue & 0xff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HID_REPORT_TYPE_FEATURE:
|
||||
if (report_id == PID_BLOCK_LOAD_REPORT) {
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 0x1; // Effect block index
|
||||
hid_report_data[2] = 0x1; // (1: success, 2: oom, 3: load error)
|
||||
hid_report_data[3] = 10;
|
||||
hid_report_data[4] = 10;
|
||||
printf_P(PSTR("block load\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 5;
|
||||
}
|
||||
else if (report_id == PID_SIMULTANEOUS_MAX) {
|
||||
hid_report_data[0] = report_id;
|
||||
// ROM Effect Block count
|
||||
hid_report_data[1] = 0x1;
|
||||
hid_report_data[2] = 0x1;
|
||||
// PID pool move report?
|
||||
hid_report_data[3] = 0xff;
|
||||
hid_report_data[4] = 1;
|
||||
printf_P(PSTR("simultaneous max\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 5;
|
||||
}
|
||||
else if (report_id == REPORT_CREATE_EFFECT) {
|
||||
hid_report_data[0] = report_id;
|
||||
hid_report_data[1] = 1;
|
||||
printf_P(PSTR("create effect\r\n"));
|
||||
*dat = hid_report_data;
|
||||
return 2;
|
||||
} else {
|
||||
printf_P(PSTR("Unknown feature %d\r\n"), rq->wValue & 0xff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
printf_P(PSTR("Unhandled hid get report type=0x%02x, rq=0x%02x, wVal=0x%04x, wLen=0x%04x\r\n"), rq->bmRequestType, rq->bRequest, rq->wValue, rq->wLength);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbpad_hid_set_report(const struct usb_request *rq, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (len < 1) {
|
||||
printf_P(PSTR("shrt\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rq->wValue >> 8) == HID_REPORT_TYPE_OUTPUT) {
|
||||
|
||||
switch(data[0])
|
||||
{
|
||||
case REPORT_SET_STATUS:
|
||||
printf_P(PSTR("eff. set stat 0x%02x 0x%02x\r\n"),data[1],data[2]);
|
||||
break;
|
||||
case REPORT_EFFECT_BLOCK_IDX:
|
||||
printf_P(PSTR("eff. blk. idx %d\r\n"), data[1]);
|
||||
break;
|
||||
case REPORT_DISABLE_ACTUATORS:
|
||||
printf_P(PSTR("disable actuators\r\n"));
|
||||
break;
|
||||
case REPORT_PID_POOL:
|
||||
printf_P(PSTR("pid pool\r\n"));
|
||||
break;
|
||||
case REPORT_SET_EFFECT:
|
||||
_FFB_effect_index = data[1];
|
||||
printf_P(PSTR("set effect %d\n"), data[1]);
|
||||
break;
|
||||
case REPORT_SET_PERIODIC:
|
||||
magnitude = data[2];
|
||||
printf_P(PSTR("periodic mag: %d"), data[2]);
|
||||
break;
|
||||
case REPORT_SET_CONSTANT_FORCE:
|
||||
if (data[1] == 1) {
|
||||
constant_force = data[2];
|
||||
//decideVibration();
|
||||
printf_P(PSTR("Constant force"));
|
||||
}
|
||||
break;
|
||||
case REPORT_EFFECT_OPERATION:
|
||||
if (len != 4)
|
||||
return -1;
|
||||
/* Byte 0 : report ID
|
||||
* Byte 1 : bit 7=rom flag, bits 6-0=effect block index
|
||||
* Byte 2 : Effect operation
|
||||
* Byte 3 : Loop count */
|
||||
_loop_count = data[3]<<3;
|
||||
|
||||
printf_P(PSTR("EFFECT OP: rom=%s, idx=0x%02x"), data[1] & 0x80 ? "Yes":"No", data[1] & 0x7F);
|
||||
|
||||
switch(data[1] & 0x7F) // Effect block index
|
||||
{
|
||||
case 1: // constant force
|
||||
case 3: // square
|
||||
case 4: // sine
|
||||
switch (data[2]) // effect operation
|
||||
{
|
||||
case EFFECT_OP_START:
|
||||
printf_P(PSTR("Start\r\n"));
|
||||
vibration_on = 1;
|
||||
// decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_START_SOLO:
|
||||
printf_P(PSTR("Start solo\r\n"));
|
||||
vibration_on = 1;
|
||||
// decideVibration();
|
||||
break;
|
||||
|
||||
case EFFECT_OP_STOP:
|
||||
printf_P(PSTR("Stop\r\n"));
|
||||
vibration_on = 0;
|
||||
// decideVibration();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// TODO : should probably drop these from the descriptor since they are
|
||||
|
||||
case 2: // ramp
|
||||
case 5: // triangle
|
||||
case 6: // sawtooth up
|
||||
case 7: // sawtooth down
|
||||
case 8: // spring
|
||||
case 9: // damper
|
||||
case 10: // inertia
|
||||
case 11: // friction
|
||||
case 12: // custom force data
|
||||
printf_P(PSTR("Ununsed effect %d\n"), data[1] & 0x7F);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf_P(PSTR("Set output report 0x%02x\r\n"), data[0]);
|
||||
}
|
||||
}
|
||||
else if ((rq->wValue >> 8) == HID_REPORT_TYPE_FEATURE) {
|
||||
switch(data[0])
|
||||
{
|
||||
case REPORT_CREATE_EFFECT:
|
||||
_FFB_effect_index = data[1];
|
||||
printf_P(PSTR("create effect %d\n"), data[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf_P(PSTR("What?\n"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf_P(PSTR("impossible\n"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
10
usbpad.h
10
usbpad.h
@ -1,9 +1,17 @@
|
||||
#ifndef USBPAD_H__
|
||||
#define USBPAD_H__
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
void usbpad_init(void);
|
||||
int usbpad_getReportSize(void);
|
||||
void usbpad_buildReport(const gamepad_data *pad_data, unsigned char *dstbuf);
|
||||
unsigned char *usbpad_getReportBuffer(void);
|
||||
|
||||
void usbpad_update(const gamepad_data *pad_data);
|
||||
char usbpad_mustVibrate(void);
|
||||
|
||||
uint8_t usbpad_hid_set_report(const struct usb_request *rq, const uint8_t *data, uint16_t len);
|
||||
uint16_t usbpad_hid_get_report(struct usb_request *rq, const uint8_t **dat);
|
||||
|
||||
// For mappings. ID starts at 0.
|
||||
#define USB_BTN(id) (0x0001 << (id))
|
||||
|
9
usbstrings.c
Normal file
9
usbstrings.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdlib.h> // for wchar_t
|
||||
#include "usbstrings.h"
|
||||
|
||||
const wchar_t *g_usb_strings[] = {
|
||||
[0] = L"raphnet technologies", // 1 : Vendor
|
||||
[1] = L"GC/N64 to USB v3.0", // 2: Product
|
||||
[2] = L"123456", // 3 : Serial
|
||||
};
|
||||
|
11
usbstrings.h
Normal file
11
usbstrings.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _usbstrings_h__
|
||||
#define _usbstrings_h__
|
||||
|
||||
extern const wchar_t *g_usb_strings[];
|
||||
|
||||
#define NUM_USB_STRINGS 3
|
||||
|
||||
/* Array indexes (i.e. zero-based0 */
|
||||
#define USB_STRING_SERIAL_IDX 2
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user