#include "mustang.h" #include Mustang::Mustang() { amp_hand = NULL; // "apply efect" command memset(execute, 0x00, LENGTH); execute[0] = 0x1c; execute[1] = 0x03; memset(prev_array, 0x00, LENGTH*4); for(int i = 0; i < 4; i++) { prev_array[i][0] = 0x1c; prev_array[i][1] = 0x03; prev_array[i][6] = prev_array[i][7] = prev_array[i][21] = 0x01; prev_array[i][20] = 0x08; prev_array[i][FXSLOT] = 0xff; } } Mustang::~Mustang() { this->stop_amp(); } int Mustang::start_amp(char list[][32], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) { int ret, received; unsigned char array[LENGTH]; unsigned char received_data[296][LENGTH], data[7][LENGTH]; memset(received_data, 0x00, 296*LENGTH); if(amp_hand == NULL) { // initialize libusb ret = libusb_init(NULL); if (ret) return ret; // get handle for the device if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, OLD_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, NEW_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, MINI_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, FLOOR_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, BRONCO40_USB_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_III_PID)) == NULL) if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_IV_PID)) == NULL) { libusb_exit(NULL); return -100; } // detach kernel driver ret = libusb_kernel_driver_active(amp_hand, 0); if(ret) { ret = libusb_detach_kernel_driver(amp_hand, 0); if(ret) { stop_amp(); return ret; } } // claim the device ret = libusb_claim_interface(amp_hand, 0); if(ret) { stop_amp(); return ret; } } // initialization which is needed if you want // to get any replies from the amp in the future memset(array, 0x00, LENGTH); array[1] = 0xc3; libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); memset(array, 0x00, LENGTH); array[0] = 0x1a; array[1] = 0x03; libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); if(list != NULL || name != NULL || amp_set != NULL || effects_set != NULL) { int i = 0, j = 0; memset(array, 0x00, LENGTH); array[0] = 0xff; array[1] = 0xc1; libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); for(i = 0; received; i++) { libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); memcpy(received_data[i], array, LENGTH); } int max_to_receive; i > 143 ? max_to_receive = 200 : max_to_receive = 48; if(list != NULL) for(i = 0, j = 0; i 0x03) { array[KNOB1] = 0x03; } array[KNOB2] = 0x00; array[KNOB3] = 0x00; array[KNOB4] = 0x00; array[KNOB5] = 0x00; break; case COMPRESSOR: array[DSP] = 0x06; array[EFFECT] = 0x07; break; case SINE_CHORUS: array[DSP] = 0x07; array[EFFECT] = 0x12; array[19] = 0x01; array[20] = 0x01; break; case TRIANGLE_CHORUS: array[DSP] = 0x07; array[EFFECT] = 0x13; array[19] = 0x01; array[20] = 0x01; break; case SINE_FLANGER: array[DSP] = 0x07; array[EFFECT] = 0x18; array[19] = 0x01; array[20] = 0x01; break; case TRIANGLE_FLANGER: array[DSP] = 0x07; array[EFFECT] = 0x19; array[19] = 0x01; array[20] = 0x01; break; case VIBRATONE: array[DSP] = 0x07; array[EFFECT] = 0x2d; array[19] = 0x01; array[20] = 0x01; break; case VINTAGE_TREMOLO: array[DSP] = 0x07; array[EFFECT] = 0x40; array[19] = 0x01; array[20] = 0x01; break; case SINE_TREMOLO: array[DSP] = 0x07; array[EFFECT] = 0x41; array[19] = 0x01; array[20] = 0x01; break; case RING_MODULATOR: array[DSP] = 0x07; array[EFFECT] = 0x22; array[19] = 0x01; if(array[KNOB4] > 0x01) { array[KNOB4] = 0x01; } break; case STEP_FILTER: array[DSP] = 0x07; array[EFFECT] = 0x29; array[19] = 0x01; array[20] = 0x01; break; case PHASER: array[DSP] = 0x07; array[EFFECT] = 0x4f; array[19] = 0x01; array[20] = 0x01; if(array[KNOB5] > 0x01) { array[KNOB5] = 0x01; } break; case PITCH_SHIFTER: array[DSP] = 0x07; array[EFFECT] = 0x1f; array[19] = 0x01; break; case MONO_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x16; array[19] = 0x02; array[20] = 0x01; break; case MONO_ECHO_FILTER: array[DSP] = 0x08; array[EFFECT] = 0x43; array[19] = 0x02; array[20] = 0x01; break; case STEREO_ECHO_FILTER: array[DSP] = 0x08; array[EFFECT] = 0x48; array[19] = 0x02; array[20] = 0x01; break; case MULTITAP_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x44; array[19] = 0x02; array[20] = 0x01; if(array[KNOB5] > 0x03) { array[KNOB5] = 0x03; } break; case PING_PONG_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x45; array[19] = 0x02; array[20] = 0x01; break; case DUCKING_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x15; array[19] = 0x02; array[20] = 0x01; break; case REVERSE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x46; array[19] = 0x02; array[20] = 0x01; break; case TAPE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x2b; array[19] = 0x02; array[20] = 0x01; break; case STEREO_TAPE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x2a; array[19] = 0x02; array[20] = 0x01; break; case SMALL_HALL_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x24; break; case LARGE_HALL_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x3a; break; case SMALL_ROOM_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x26; break; case LARGE_ROOM_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x3b; break; case SMALL_PLATE_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4e; break; case LARGE_PLATE_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4b; break; case AMBIENT_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4c; break; case ARENA_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4d; break; case FENDER_63_SPRING_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x21; break; case FENDER_65_SPRING_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x0b; break; } // send packet to the amp ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); //DEBUG // qDebug("set: DSP: %d, slot: %d, effect: %d", array[DSP], array[FXSLOT], array[EFFECT]); // save current settings memcpy(prev_array[array[DSP]-6], array, LENGTH); //DEBUG // FILE *f; // static char trynum=0; // char mes[16]; // sprintf(mes, "test%d.bin",trynum); // f=fopen(mes,"w"); // fwrite(array, sizeof(array), 1, f); // //fwrite(execute, sizeof(execute), 1, f); // fclose(f); // trynum++; return ret; } int Mustang::effect_toggle(int category, int state) { int ret, received; unsigned char array[LENGTH]; memset(array, 0x00, LENGTH); array[0] = 0x19; array[1] = 0xc3; // Translate DSP to internal effect category array[2] = prev_array[category][DSP] - 3; array[3] = state; array[FXSLOT] = prev_array[category][FXSLOT]; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); // flush reply data for (int i=0; received; i++) { libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); } return ret; } int Mustang::set_amplifier(struct amp_settings value) { int ret, received; unsigned char array[LENGTH] = { 0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xa2, 0x80, 0x63, 0x99, 0x80, 0xb0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x07, 0x07, 0x07, 0x05, 0x00, 0x07, 0x07, 0x01, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; array[DSP] = 0x05; array[GAIN] = value.gain; array[VOLUME] = value.volume; array[TREBLE] = value.treble; array[MIDDLE] = value.middle; array[BASS] = value.bass; if(value.cabinet > 0x0c) array[CABINET] = 0x00; else array[CABINET] = value.cabinet; if(value.noise_gate > 0x05) array[NOISE_GATE] = 0x00; else array[NOISE_GATE] = value.noise_gate; array[MASTER_VOL] = value.master_vol; array[GAIN2] = value.gain2; array[PRESENCE] = value.presence; if(value.noise_gate == 0x05) { if(value.threshold > 0x09) array[THRESHOLD] = 0x00; else array[THRESHOLD] = value.threshold; array[DEPTH] = value.depth; } array[BIAS] = value.bias; if(value.sag > 0x02) array[SAG] = 0x01; else array[SAG] = value.sag; array[BRIGHTNESS] = value.brightness?1:0; switch (value.amp_num) { case STUDIO_PREAMP: array[AMPLIFIER] = 0xf1; array[44] = array[45] = array[46] = 0x0d; array[50] = 0x0d; array[54] = 0xf6; break; case FENDER_57_CHAMP: array[AMPLIFIER] = 0x7c; array[44] = array[45] = array[46] = 0x0c; array[50] = 0x0c; array[54] = 0x00; break; case FENDER_57_DELUXE: array[AMPLIFIER] = 0x67; array[44] = array[45] = array[46] = 0x01; array[50] = 0x01; array[54] = 0x53; break; case FENDER_57_TWIN: array[AMPLIFIER] = 0xf6; array[44] = array[45] = array[46] = 0x0e; array[50] = 0x0e; array[54] = 0xf9; break; case FENDER_59_BASSMAN: array[AMPLIFIER] = 0x64; array[44] = array[45] = array[46] = 0x02; array[50] = 0x02; array[54] = 0x67; break; case FENDER_65_PRINCETON: array[AMPLIFIER] = 0x6a; array[44] = array[45] = array[46] = 0x04; array[50] = 0x04; array[54] = 0x61; break; case FENDER_65_DELUXE_REVERB: array[AMPLIFIER] = 0x53; array[40] = array[43] = 0x00; array[44] = array[45] = array[46] = 0x03; array[50] = 0x03; array[54] = 0x6a; break; case FENDER_65_TWIN_REVERB: array[AMPLIFIER] = 0x75; array[44] = array[45] = array[46] = 0x05; array[50] = 0x05; array[54] = 0x72; break; case S60S_THRIFT: array[AMPLIFIER] = 0xf9; array[44] = array[45] = array[46] = 0x0f; array[50] = 0x0f; array[54] = 0xfc; break; case BRITISH_WATTS: array[AMPLIFIER] = 0xff; array[44] = array[45] = array[46] = 0x11; array[50] = 0x11; array[54] = 0x00; break; case BRITISH_60S: array[AMPLIFIER] = 0x61; array[44] = array[45] = array[46] = 0x07; array[50] = 0x07; array[54] = 0x5e; break; case BRITISH_70S: array[AMPLIFIER] = 0x79; array[44] = array[45] = array[46] = 0x0b; array[50] = 0x0b; array[54] = 0x7c; break; case BRITISH_80S: array[AMPLIFIER] = 0x5e; array[44] = array[45] = array[46] = 0x09; array[50] = 0x09; array[54] = 0x5d; break; case BRITISH_COLOUR: array[AMPLIFIER] = 0xfc; array[44] = array[45] = array[46] = 0x10; array[50] = 0x10; array[54] = 0xff; break; case FENDER_SUPER_SONIC: array[AMPLIFIER] = 0x72; array[44] = array[45] = array[46] = 0x06; array[50] = 0x06; array[54] = 0x79; break; case AMERICAN_90S: array[AMPLIFIER] = 0x5d; array[44] = array[45] = array[46] = 0x0a; array[50] = 0x0a; array[54] = 0x6d; break; case METAL_2000: array[AMPLIFIER] = 0x6d; array[44] = array[45] = array[46] = 0x08; array[50] = 0x08; array[54] = 0x75; break; } ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); memset(array, 0x00, LENGTH); array[0] = 0x1c; array[1] = 0x03; array[2] = 0x0d; array[6] = 0x01; array[7] = 0x01; array[16] = value.usb_gain; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); return ret; } int Mustang::save_on_amp(char *name, int slot) { int ret, received; unsigned char array[LENGTH]; memset(array, 0x00, LENGTH); array[0] = 0x1c; array[1] = 0x01; array[2] = 0x03; array[SAVE_SLOT] = slot; array[6] = 0x01; array[7] = 0x01; if(strlen(name) > 31) name[31] = 0x00; for(unsigned int i = 16, j = 0; name[j] != 0x00; i++,j++) array[i] = name[j]; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); load_memory_bank(slot, NULL, NULL, NULL); return ret; } int Mustang::load_memory_bank(int slot, char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) { int ret, received; unsigned char array[LENGTH], data[7][LENGTH]; memset(array, 0x00, LENGTH); array[0] = 0x1c; array[1] = 0x01; array[2] = 0x01; array[SAVE_SLOT] = slot; array[6] = 0x01; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); for(int i = 0; received; i++) { libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); if(i < 7) memcpy(data[i], array, LENGTH); } if(name != NULL || amp_set != NULL || effects_set != NULL) decode_data(data, name, amp_set, effects_set); return ret; } int Mustang::decode_data(unsigned char data[6][LENGTH], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) { if(name != NULL) { // NAME memset(name, 0x00, 32); for(int i = 0, j = 16; data[0][j] != 0x00; i++, j++) name[i] = data[0][j]; } if(amp_set != NULL) { // AMPLIFIER switch(data[1][AMPLIFIER]) { case 0xf1: amp_set->amp_num = STUDIO_PREAMP; break; case 0x7c: amp_set->amp_num = FENDER_57_CHAMP; break; case 0x67: amp_set->amp_num = FENDER_57_DELUXE; break; case 0xf6: amp_set->amp_num = FENDER_57_TWIN; break; case 0x64: amp_set->amp_num = FENDER_59_BASSMAN; break; case 0x6a: amp_set->amp_num = FENDER_65_PRINCETON; break; case 0x53: amp_set->amp_num = FENDER_65_DELUXE_REVERB; break; case 0x75: amp_set->amp_num = FENDER_65_TWIN_REVERB; break; case 0xf9: amp_set->amp_num = S60S_THRIFT; break; case 0xff: amp_set->amp_num = BRITISH_WATTS; break; case 0x61: amp_set->amp_num = BRITISH_60S; break; case 0x79: amp_set->amp_num = BRITISH_70S; break; case 0x5e: amp_set->amp_num = BRITISH_80S; break; case 0xfc: amp_set->amp_num = BRITISH_COLOUR; break; case 0x72: amp_set->amp_num = FENDER_SUPER_SONIC; break; case 0x5d: amp_set->amp_num = AMERICAN_90S; break; case 0x6d: amp_set->amp_num = METAL_2000; break; default: amp_set->amp_num = STUDIO_PREAMP; break; } // STUDIO_PREAMP, // FENDER_57_CHAMP, // FENDER_57_DELUXE, // FENDER_57_TWIN, // FENDER_59_BASSMAN, // FENDER_65_PRINCETON, // FENDER_65_DELUXE_REVERB, // FENDER_65_TWIN_REVERB, // S60S_THRIFT, // BRITISH_WATTS, // BRITISH_60S, // BRITISH_70S, // BRITISH_80S, // BRITISH_COLOUR, // FENDER_SUPER_SONIC, // AMERICAN_90S, // METAL_2000 amp_set->gain = data[1][GAIN]; amp_set->volume = data[1][VOLUME]; amp_set->treble = data[1][TREBLE]; amp_set->middle = data[1][MIDDLE]; amp_set->bass = data[1][BASS]; amp_set->cabinet = data[1][CABINET]; amp_set->noise_gate = data[1][NOISE_GATE]; amp_set->master_vol = data[1][MASTER_VOL]; amp_set->gain2 = data[1][GAIN2]; amp_set->presence = data[1][PRESENCE]; amp_set->threshold = data[1][THRESHOLD]; amp_set->depth = data[1][DEPTH]; amp_set->bias = data[1][BIAS]; amp_set->sag = data[1][SAG]; amp_set->brightness = data[1][BRIGHTNESS]?true:false; amp_set->usb_gain = data[6][16]; } if(effects_set != NULL) { // EFFECTS for(int i = 2; i < 6; i++) { int j=0; prev_array[data[i][DSP]-6][0] = 0x1c; prev_array[data[i][DSP]-6][1] = 0x03; prev_array[data[i][DSP]-6][FXSLOT] = data[i][FXSLOT]; prev_array[data[i][DSP]-6][DSP] = data[i][DSP]; prev_array[data[i][DSP]-6][19] = data[i][19]; prev_array[data[i][DSP]-6][20] = data[i][20]; switch(data[i][FXSLOT]) { case 0x00: case 0x04: j = 0; break; case 0x01: case 0x05: j = 1; break; case 0x02: case 0x06: j = 2; break; case 0x03: case 0x07: j = 3; break; default: j=0; break; } effects_set[j].fx_slot = j; effects_set[j].knob1 = data[i][KNOB1]; effects_set[j].knob2 = data[i][KNOB2]; effects_set[j].knob3 = data[i][KNOB3]; effects_set[j].knob4 = data[i][KNOB4]; effects_set[j].knob5 = data[i][KNOB5]; effects_set[j].knob6 = data[i][KNOB6]; if(data[i][FXSLOT] > 0x03) effects_set[j].put_post_amp = true; else effects_set[j].put_post_amp = false; switch(data[i][EFFECT]) { case 0x00: effects_set[j].effect_num = EMPTY; break; case 0x3c: effects_set[j].effect_num = OVERDRIVE; break; case 0x49: effects_set[j].effect_num = WAH; break; case 0x4a: effects_set[j].effect_num = TOUCH_WAH; break; case 0x1a: effects_set[j].effect_num = FUZZ; break; case 0x1c: effects_set[j].effect_num = FUZZ_TOUCH_WAH; break; case 0x88: effects_set[j].effect_num = SIMPLE_COMP; break; case 0x07: effects_set[j].effect_num = COMPRESSOR; break; case 0x12: effects_set[j].effect_num = SINE_CHORUS; break; case 0x13: effects_set[j].effect_num = TRIANGLE_CHORUS; break; case 0x18: effects_set[j].effect_num = SINE_FLANGER; break; case 0x19: effects_set[j].effect_num = TRIANGLE_FLANGER; break; case 0x2d: effects_set[j].effect_num = VIBRATONE; break; case 0x40: effects_set[j].effect_num = VINTAGE_TREMOLO; break; case 0x41: effects_set[j].effect_num = SINE_TREMOLO; break; case 0x22: effects_set[j].effect_num = RING_MODULATOR; break; case 0x29: effects_set[j].effect_num = STEP_FILTER; break; case 0x4f: effects_set[j].effect_num = PHASER; break; case 0x1f: effects_set[j].effect_num = PITCH_SHIFTER; break; case 0x16: effects_set[j].effect_num = MONO_DELAY; break; case 0x43: effects_set[j].effect_num = MONO_ECHO_FILTER; break; case 0x48: effects_set[j].effect_num = STEREO_ECHO_FILTER; break; case 0x44: effects_set[j].effect_num = MULTITAP_DELAY; break; case 0x45: effects_set[j].effect_num = PING_PONG_DELAY; break; case 0x15: effects_set[j].effect_num = DUCKING_DELAY; break; case 0x46: effects_set[j].effect_num = REVERSE_DELAY; break; case 0x2b: effects_set[j].effect_num = TAPE_DELAY; break; case 0x2a: effects_set[j].effect_num = STEREO_TAPE_DELAY; break; case 0x24: effects_set[j].effect_num = SMALL_HALL_REVERB; break; case 0x3a: effects_set[j].effect_num = LARGE_HALL_REVERB; break; case 0x26: effects_set[j].effect_num = SMALL_ROOM_REVERB; break; case 0x3b: effects_set[j].effect_num = LARGE_ROOM_REVERB; break; case 0x4e: effects_set[j].effect_num = SMALL_PLATE_REVERB; break; case 0x4b: effects_set[j].effect_num = LARGE_PLATE_REVERB; break; case 0x4c: effects_set[j].effect_num = AMBIENT_REVERB; break; case 0x4d: effects_set[j].effect_num = ARENA_REVERB; break; case 0x21: effects_set[j].effect_num = FENDER_63_SPRING_REVERB; break; case 0x0b: effects_set[j].effect_num = FENDER_65_SPRING_REVERB; break; default: effects_set[j].effect_num = EMPTY; break; } } } return 0; } int Mustang::save_effects(int slot, char name[24], int number_of_effects, struct fx_pedal_settings effects[2]) { int ret, received; unsigned char fxknob, repeat; unsigned char temp[LENGTH], array[LENGTH] = { 0x1c, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; execute[2]=0x00; // why this must be here? if(number_of_effects > 2) repeat = 1; else repeat = number_of_effects; for(int i = 0; i < repeat; i++) if(effects[i].effect_num < SINE_CHORUS) return -1; if(effects[0].effect_num>=SINE_CHORUS && effects[0].effect_num<=PITCH_SHIFTER) { fxknob = 0x01; repeat = 1; //just to be sure } else fxknob = 0x02; array[FXKNOB] = fxknob; array[SAVE_SLOT] = slot; // set and send the name if(name[24] != 0x00) name[24] = 0x00; for(int i = 0, j = 16; name[i] != 0x00; i++, j++) array[j] = name[i]; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); array[1] = 0x03; array[6] = 0x00; memset(array+16, 0x00, LENGTH-16); for(int i = 0; i < repeat; i++) { array[19] = 0x00; array[20] = 0x08; array[21] = 0x01; array[KNOB6] = 0x00; if(effects[i].put_post_amp) array[FXSLOT] = effects[i].fx_slot+4; else array[FXSLOT] = effects[i].fx_slot; array[KNOB1] = effects[i].knob1; array[KNOB2] = effects[i].knob2; array[KNOB3] = effects[i].knob3; array[KNOB4] = effects[i].knob4; array[KNOB5] = effects[i].knob5; // some effects have more knobs if (effects[i].effect_num == MONO_ECHO_FILTER || effects[i].effect_num == STEREO_ECHO_FILTER || effects[i].effect_num == TAPE_DELAY || effects[i].effect_num == STEREO_TAPE_DELAY) { array[KNOB6] = effects[i].knob6; } // fill the form with missing data switch (effects[i].effect_num) { case SINE_CHORUS: array[DSP] = 0x07; array[EFFECT] = 0x12; array[19] = 0x01; array[20] = 0x01; break; case TRIANGLE_CHORUS: array[DSP] = 0x07; array[EFFECT] = 0x13; array[19] = 0x01; array[20] = 0x01; break; case SINE_FLANGER: array[DSP] = 0x07; array[EFFECT] = 0x18; array[19] = 0x01; array[20] = 0x01; break; case TRIANGLE_FLANGER: array[DSP] = 0x07; array[EFFECT] = 0x19; array[19] = 0x01; array[20] = 0x01; break; case VIBRATONE: array[DSP] = 0x07; array[EFFECT] = 0x2d; array[19] = 0x01; array[20] = 0x01; break; case VINTAGE_TREMOLO: array[DSP] = 0x07; array[EFFECT] = 0x40; array[19] = 0x01; array[20] = 0x01; break; case SINE_TREMOLO: array[DSP] = 0x07; array[EFFECT] = 0x41; array[19] = 0x01; array[20] = 0x01; break; case RING_MODULATOR: array[DSP] = 0x07; array[EFFECT] = 0x22; array[19] = 0x01; if(array[KNOB4] > 0x01) array[KNOB4] = 0x01; break; case STEP_FILTER: array[DSP] = 0x07; array[EFFECT] = 0x29; array[19] = 0x01; array[20] = 0x01; break; case PHASER: array[DSP] = 0x07; array[EFFECT] = 0x4f; array[19] = 0x01; array[20] = 0x01; if(array[KNOB5] > 0x01) array[KNOB5] = 0x01; break; case PITCH_SHIFTER: array[DSP] = 0x07; array[EFFECT] = 0x1f; array[19] = 0x01; break; case MONO_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x16; array[19] = 0x02; array[20] = 0x01; break; case MONO_ECHO_FILTER: array[DSP] = 0x08; array[EFFECT] = 0x43; array[19] = 0x02; array[20] = 0x01; break; case STEREO_ECHO_FILTER: array[DSP] = 0x08; array[EFFECT] = 0x48; array[19] = 0x02; array[20] = 0x01; break; case MULTITAP_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x44; array[19] = 0x02; array[20] = 0x01; break; case PING_PONG_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x45; array[19] = 0x02; array[20] = 0x01; break; case DUCKING_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x15; array[19] = 0x02; array[20] = 0x01; break; case REVERSE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x46; array[19] = 0x02; array[20] = 0x01; break; case TAPE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x2b; array[19] = 0x02; array[20] = 0x01; break; case STEREO_TAPE_DELAY: array[DSP] = 0x08; array[EFFECT] = 0x2a; array[19] = 0x02; array[20] = 0x01; break; case SMALL_HALL_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x24; break; case LARGE_HALL_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x3a; break; case SMALL_ROOM_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x26; break; case LARGE_ROOM_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x3b; break; case SMALL_PLATE_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4e; break; case LARGE_PLATE_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4b; break; case AMBIENT_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4c; break; case ARENA_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x4d; break; case FENDER_63_SPRING_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x21; break; case FENDER_65_SPRING_REVERB: array[DSP] = 0x09; array[EFFECT] = 0x0b; break; } // send packet ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); } execute[FXKNOB] = fxknob; ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); execute[FXKNOB] = 0x00; return 0; } int Mustang::update(char *filename) { int ret, received; unsigned char array[LENGTH], number = 0; FILE *file; // struct timespec sleep; // sleep.tv_nsec = NANO_SEC_SLEEP; // sleep.tv_sec = 0; if(amp_hand == NULL) { // initialize libusb ret = libusb_init(NULL); if (ret) return ret; // get handle for the device amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, OLD_USB_UPDATE_PID); if(amp_hand == NULL) { amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, NEW_USB_UPDATE_PID); if(amp_hand == NULL) { amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, MINI_USB_UPDATE_PID); if(amp_hand == NULL) { amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, FLOOR_USB_UPDATE_PID); if(amp_hand == NULL) { libusb_exit(NULL); return -100; } } } } // detach kernel driver ret = libusb_kernel_driver_active(amp_hand, 0); if(ret) { ret = libusb_detach_kernel_driver(amp_hand, 0); if(ret) { stop_amp(); return ret; } } // claim the device ret = libusb_claim_interface(amp_hand, 0); if(ret) { stop_amp(); return ret; } } else return -200; file = fopen(filename, "rb"); // send date when firmware was created fseek(file, 0x1a, SEEK_SET); memset(array, 0x00, LENGTH); array[0] = 0x02; array[1] = 0x03; array[2] = 0x01; array[3] = 0x06; int rc = fread(array+4, 1, 11, file); ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); // nanosleep(&sleep, NULL); usleep(10000); // send firmware fseek(file, 0x110, SEEK_SET); for(;;) { memset(array, 0x00, LENGTH); array[0] = array[1] = 0x03; array[2] = number; number++; array[3] = fread(array+4, 1, LENGTH-8, file); ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); // nanosleep(&sleep, NULL); usleep(10000); if(feof(file)) // if reached end of the file break; // exit loop } fclose(file); // send "finished" packet memset(array, 0x00, LENGTH); array[0] = 0x04; array[1] = 0x03; ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); // release claimed interface ret = libusb_release_interface(amp_hand, 0); if(ret) return ret; // re-attach kernel driver ret = libusb_attach_kernel_driver(amp_hand, 0); if(ret) return ret; // close opened interface libusb_close(amp_hand); amp_hand = NULL; // stop using libusb libusb_exit(NULL); return 0; }