Start bootloader by USB message

This commit is contained in:
Raphael Assenat 2015-08-16 01:59:38 -04:00
parent 06bea508f1
commit a84b70c369
7 changed files with 133 additions and 19 deletions

View File

@ -9,7 +9,7 @@ CFLAGS=-Wall -mmcu=$(CPU) -DF_CPU=16000000L -Os -DUART1_STDOUT
LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map LDFLAGS=-mmcu=$(CPU) -Wl,-Map=$(PROGNAME).map
HEXFILE=$(PROGNAME).hex HEXFILE=$(PROGNAME).hex
OBJS=main.o n64.o gcn64_protocol.o usart1.o usb.o OBJS=main.o n64.o gcn64_protocol.o usart1.o usb.o bootloader.o
all: $(HEXFILE) all: $(HEXFILE)

17
bootloader.c Normal file
View File

@ -0,0 +1,17 @@
#include <avr/io.h>
#include "usb.h"
void enterBootLoader(void)
{
usb_shutdown();
// AT90USB1287/1286 : 0xF000 (word address)
// ATmega32u2 : ???
asm volatile(
"cli \n"
"ldi r30, 0x00 \n" // ZL
"ldi r31, 0xF0 \n" // ZH
"ijmp");
}

2
bootloader.h Normal file
View File

@ -0,0 +1,2 @@
void enterBootLoader(void);

15
dataHidReport.c Normal file
View File

@ -0,0 +1,15 @@
#include <avr/pgmspace.h>
#include <ctype.h>
const uint8_t dataHidReport[] PROGMEM = {
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x05, // REPORT_COUNT (5)
0x09, 0x01, // USAGE (Vendor defined)
0xB1, 0x00, // FEATURE (Data,Ary,Abs)
0xc0 // END_COLLECTION
};

102
main.c
View File

@ -7,24 +7,22 @@
#include <util/delay.h> #include <util/delay.h>
#include "util.h"
#include "usart1.h" #include "usart1.h"
#include "usb.h" #include "usb.h"
#include "gamepad.h" #include "gamepad.h"
#include "gcn64_protocol.h" #include "gcn64_protocol.h"
#include "n64.h" #include "n64.h"
#include "bootloader.h"
#ifndef ARRAY_SIZE uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat);
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
#endif
#ifndef LPSTR uint16_t hid_get_report_data(struct usb_request *rq, const uint8_t **dat);
#define LPSTR(s) ((const PROGMEM wchar_t*)(s)) uint8_t hid_set_report_data(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
#endif
uint16_t hid_get_report(struct usb_request *rq, const uint8_t **dat);
uint8_t hid_set_report(const struct usb_request *rq, const uint8_t *dat, uint16_t len);
#include "reportdesc.c" #include "reportdesc.c"
#include "dataHidReport.c"
const wchar_t *const g_usb_strings[] = { const wchar_t *const g_usb_strings[] = {
[0] = L"raphnet technologies", // 1 : Vendor [0] = L"raphnet technologies", // 1 : Vendor
@ -37,6 +35,10 @@ struct cfg0 {
struct usb_interface_descriptor interface; struct usb_interface_descriptor interface;
struct usb_hid_descriptor hid; struct usb_hid_descriptor hid;
struct usb_endpoint_descriptor ep1_in; struct usb_endpoint_descriptor ep1_in;
struct usb_interface_descriptor interface_admin;
struct usb_hid_descriptor hid_data;
struct usb_endpoint_descriptor ep2_in;
}; };
static const struct cfg0 cfg0 PROGMEM = { static const struct cfg0 cfg0 PROGMEM = {
@ -44,11 +46,13 @@ static const struct cfg0 cfg0 PROGMEM = {
.bLength = sizeof(struct usb_configuration_descriptor), .bLength = sizeof(struct usb_configuration_descriptor),
.bDescriptorType = CONFIGURATION_DESCRIPTOR, .bDescriptorType = CONFIGURATION_DESCRIPTOR,
.wTotalLength = sizeof(cfg0), // includes all descriptors returned together .wTotalLength = sizeof(cfg0), // includes all descriptors returned together
.bNumInterfaces = 1, .bNumInterfaces = 2,
.bConfigurationValue = 1, .bConfigurationValue = 1,
.bmAttributes = CFG_DESC_ATTR_RESERVED, // set Self-powred and remote-wakeup here if needed. .bmAttributes = CFG_DESC_ATTR_RESERVED, // set Self-powred and remote-wakeup here if needed.
.bMaxPower = 25, // for 50mA .bMaxPower = 25, // for 50mA
}, },
// Main interface, HID
.interface = { .interface = {
.bLength = sizeof(struct usb_interface_descriptor), .bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = INTERFACE_DESCRIPTOR, .bDescriptorType = INTERFACE_DESCRIPTOR,
@ -76,6 +80,36 @@ static const struct cfg0 cfg0 PROGMEM = {
.wMaxPacketsize = 64, .wMaxPacketsize = 64,
.bInterval = LS_FS_INTERVAL_MS(1), .bInterval = LS_FS_INTERVAL_MS(1),
}, },
// Second HID interface for config and update
.interface_admin = {
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = INTERFACE_DESCRIPTOR,
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_DEVICE_CLASS_HID,
.bInterfaceSubClass = HID_SUBCLASS_NONE,
.bInterfaceProtocol = HID_PROTOCOL_NONE,
},
.hid_data = {
.bLength = sizeof(struct usb_hid_descriptor),
.bDescriptorType = HID_DESCRIPTOR,
.bcdHid = 0x0101,
.bCountryCode = HID_COUNTRY_NOT_SUPPORTED,
.bNumDescriptors = 1, // Only a report descriptor
.bClassDescriptorType = REPORT_DESCRIPTOR,
.wClassDescriptorLength = sizeof(dataHidReport),
},
.ep2_in = {
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = ENDPOINT_DESCRIPTOR,
.bEndpointAddress = USB_RQT_DEVICE_TO_HOST | 2, // 0x82
.bmAttributes = TRANSFER_TYPE_INT,
.wMaxPacketsize = 64,
.bInterval = LS_FS_INTERVAL_MS(1),
},
}; };
const struct usb_device_descriptor device_descriptor PROGMEM = { const struct usb_device_descriptor device_descriptor PROGMEM = {
@ -95,6 +129,8 @@ const struct usb_device_descriptor device_descriptor PROGMEM = {
.iSerialNumber = 3, .iSerialNumber = 3,
}; };
/** **/
static struct usb_parameters usb_params = { static struct usb_parameters usb_params = {
.flags = USB_PARAM_FLAG_CONFDESC_PROGMEM | .flags = USB_PARAM_FLAG_CONFDESC_PROGMEM |
USB_PARAM_FLAG_DEVDESC_PROGMEM | USB_PARAM_FLAG_DEVDESC_PROGMEM |
@ -104,10 +140,22 @@ static struct usb_parameters usb_params = {
.configdesc_ttllen = sizeof(cfg0), .configdesc_ttllen = sizeof(cfg0),
.num_strings = ARRAY_SIZE(g_usb_strings), .num_strings = ARRAY_SIZE(g_usb_strings),
.strings = g_usb_strings, .strings = g_usb_strings,
.reportdesc = gcn64_usbHidReportDescriptor,
.reportdesc_len = sizeof(gcn64_usbHidReportDescriptor), .n_hid_interfaces = 2,
.getReport = hid_get_report, .hid_params = {
.setReport = hid_set_report, [0] = {
.reportdesc = gcn64_usbHidReportDescriptor,
.reportdesc_len = sizeof(gcn64_usbHidReportDescriptor),
.getReport = hid_get_report_main,
.setReport = hid_set_report_main,
},
[1] = {
.reportdesc = dataHidReport,
.reportdesc_len = sizeof(dataHidReport),
.getReport = hid_get_report_data,
.setReport = hid_set_report_data,
},
},
}; };
void hwinit(void) void hwinit(void)
@ -221,13 +269,14 @@ static void decideVibration(void)
} }
} }
uint16_t hid_get_report(struct usb_request *rq, const uint8_t **dat) uint16_t hid_get_report_main(struct usb_request *rq, const uint8_t **dat)
{ {
uint8_t report_id = (rq->wValue & 0xff); uint8_t report_id = (rq->wValue & 0xff);
// USB HID 1.11 section 7.2.1 Get_Report // USB HID 1.11 section 7.2.1 Get_Report
// wValue high byte : report type // wValue high byte : report type
// wValue low byte : report id // wValue low byte : report id
// wIndex Interface
switch (rq->wValue >> 8) switch (rq->wValue >> 8)
{ {
case HID_REPORT_TYPE_INPUT: case HID_REPORT_TYPE_INPUT:
@ -290,7 +339,7 @@ uint16_t hid_get_report(struct usb_request *rq, const uint8_t **dat)
return 0; return 0;
} }
uint8_t hid_set_report(const struct usb_request *rq, const uint8_t *data, uint16_t len) uint8_t hid_set_report_main(const struct usb_request *rq, const uint8_t *data, uint16_t len)
{ {
if (len < 1) { if (len < 1) {
printf_P(PSTR("shrt\n")); printf_P(PSTR("shrt\n"));
@ -394,6 +443,27 @@ uint8_t hid_set_report(const struct usb_request *rq, const uint8_t *data, uint16
return 0; return 0;
} }
uint16_t hid_get_report_data(struct usb_request *rq, const uint8_t **dat)
{
printf("Get data\n");
return 0;
}
uint8_t hid_set_report_data(const struct usb_request *rq, const uint8_t *dat, uint16_t len)
{
int i;
printf("Set data %d\n", len);
for (i=0; i<len; i++) {
printf("0x%02x ", dat[i]);
}
printf("\n");
enterBootLoader();
return 0;
}
int main(void) int main(void)
{ {
Gamepad *pad = NULL; Gamepad *pad = NULL;

4
usb.c
View File

@ -627,7 +627,7 @@ void usb_shutdown(void)
UDIEN = 0; UDIEN = 0;
USBCON &= (1<<USBE); USBCON &= ~(1<<USBE);
USBCON |= (1<<FRZCLK); // initial value USBCON |= (1<<FRZCLK); // initial value
#ifdef UHWCON #ifdef UHWCON
UHWCON &= ~(1<<UVREGE); // Disable USB pad regulator UHWCON &= ~(1<<UVREGE); // Disable USB pad regulator
@ -710,7 +710,7 @@ void usb_init(const struct usb_parameters *params)
g_params = params; g_params = params;
// Set some initial values // Set some initial values
USBCON &= (1<<USBE); USBCON &= ~(1<<USBE);
USBCON |= (1<<FRZCLK); // initial value USBCON |= (1<<FRZCLK); // initial value
#ifdef UHWCON #ifdef UHWCON
UHWCON |= (1<<UVREGE); // Enable USB pad regulator UHWCON |= (1<<UVREGE); // Enable USB pad regulator

10
util.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#endif
#ifndef LPSTR
#define LPSTR(s) ((const PROGMEM wchar_t*)(s))
#endif