#| | #| | ||||
set( CHIP | set( CHIP | ||||
"mk20dx128vlf5" # McHCK mk20dx128vlf5 | "mk20dx128vlf5" # McHCK mk20dx128vlf5 | ||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | |||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | |||||
) | ) | ||||
#| Stick with gcc unless you know what you're doing | #| Stick with gcc unless you know what you're doing | ||||
#| Currently only arm is supported with clang | #| Currently only arm is supported with clang | ||||
set( COMPILER | set( COMPILER | ||||
"gcc" # arm-none-eabi-gcc / avr-gcc - Default | |||||
# "clang" # arm-none-eabi | |||||
"gcc" # arm-none-eabi-gcc / avr-gcc - Default | |||||
# "clang" # arm-none-eabi | |||||
CACHE STRING "Compiler Type" ) | CACHE STRING "Compiler Type" ) | ||||
void dfu_write_done( enum dfu_status err, struct dfu_ctx *ctx ) | void dfu_write_done( enum dfu_status err, struct dfu_ctx *ctx ) | ||||
{ | { | ||||
ctx->status = err; | |||||
if (ctx->status == DFU_STATUS_OK) { | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuDNBUSY: | |||||
ctx->state = DFU_STATE_dfuDNLOAD_IDLE; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} else { | |||||
ctx->state = DFU_STATE_dfuERROR; | |||||
} | |||||
ctx->status = err; | |||||
if (ctx->status == DFU_STATUS_OK) { | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuDNBUSY: | |||||
ctx->state = DFU_STATE_dfuDNLOAD_IDLE; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} else { | |||||
ctx->state = DFU_STATE_dfuERROR; | |||||
} | |||||
} | } | ||||
static void dfu_dnload_complete( void *buf, ssize_t len, void *cbdata ) | static void dfu_dnload_complete( void *buf, ssize_t len, void *cbdata ) | ||||
{ | { | ||||
struct dfu_ctx *ctx = cbdata; | |||||
struct dfu_ctx *ctx = cbdata; | |||||
if (len > 0) | |||||
ctx->state = DFU_STATE_dfuDNBUSY; | |||||
else | |||||
ctx->state = DFU_STATE_dfuMANIFEST; | |||||
ctx->status = ctx->finish_write(buf, ctx->off, len); | |||||
ctx->off += len; | |||||
ctx->len = len; | |||||
if (len > 0) | |||||
ctx->state = DFU_STATE_dfuDNBUSY; | |||||
else | |||||
ctx->state = DFU_STATE_dfuMANIFEST; | |||||
ctx->status = ctx->finish_write(buf, ctx->off, len); | |||||
ctx->off += len; | |||||
ctx->len = len; | |||||
if (ctx->status != DFU_STATUS_async) | |||||
dfu_write_done(ctx->status, ctx); | |||||
if (ctx->status != DFU_STATUS_async) | |||||
dfu_write_done(ctx->status, ctx); | |||||
usb_handle_control_status(ctx->state == DFU_STATE_dfuERROR); | |||||
usb_handle_control_status(ctx->state == DFU_STATE_dfuERROR); | |||||
} | } | ||||
static void dfu_reset_system( void *buf, ssize_t len, void *cbdata ) | static void dfu_reset_system( void *buf, ssize_t len, void *cbdata ) | ||||
{ | { | ||||
SOFTWARE_RESET(); | |||||
SOFTWARE_RESET(); | |||||
} | } | ||||
static int dfu_handle_control( struct usb_ctrl_req_t *req, void *data ) | static int dfu_handle_control( struct usb_ctrl_req_t *req, void *data ) | ||||
{ | { | ||||
struct dfu_ctx *ctx = data; | |||||
int fail = 1; | |||||
switch ((enum dfu_ctrl_req_code)req->bRequest) { | |||||
case USB_CTRL_REQ_DFU_DNLOAD: { | |||||
void *buf; | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuIDLE: | |||||
ctx->off = 0; | |||||
break; | |||||
case DFU_STATE_dfuDNLOAD_IDLE: | |||||
break; | |||||
default: | |||||
goto err; | |||||
} | |||||
/** | |||||
* XXX we are not allowed to STALL here, and we need to eat all transferred data. | |||||
* better not allow setup_write to break the protocol. | |||||
*/ | |||||
ctx->status = ctx->setup_write(ctx->off, req->wLength, &buf); | |||||
if (ctx->status != DFU_STATUS_OK) { | |||||
ctx->state = DFU_STATE_dfuERROR; | |||||
goto err_have_status; | |||||
} | |||||
if (req->wLength > 0) | |||||
usb_ep0_rx(buf, req->wLength, dfu_dnload_complete, ctx); | |||||
else | |||||
dfu_dnload_complete(NULL, 0, ctx); | |||||
goto out_no_status; | |||||
} | |||||
case USB_CTRL_REQ_DFU_GETSTATUS: { | |||||
struct dfu_status_t st; | |||||
st.bState = ctx->state; | |||||
st.bStatus = ctx->status; | |||||
st.bwPollTimeout = 1000; /* XXX */ | |||||
/** | |||||
* If we're in DFU_STATE_dfuMANIFEST, we just finished | |||||
* the download, and we're just about to send our last | |||||
* status report. Once the report has been sent, go | |||||
* and reset the system to put the new firmware into | |||||
* effect. | |||||
*/ | |||||
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL); | |||||
if (ctx->state == DFU_STATE_dfuMANIFEST) { | |||||
usb_handle_control_status_cb(dfu_reset_system); | |||||
goto out_no_status; | |||||
} | |||||
break; | |||||
} | |||||
case USB_CTRL_REQ_DFU_CLRSTATUS: | |||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
ctx->status = DFU_STATUS_OK; | |||||
break; | |||||
case USB_CTRL_REQ_DFU_GETSTATE: { | |||||
uint8_t st = ctx->state; | |||||
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL); | |||||
break; | |||||
} | |||||
case USB_CTRL_REQ_DFU_ABORT: | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuIDLE: | |||||
case DFU_STATE_dfuDNLOAD_IDLE: | |||||
/* case DFU_STATE_dfuUPLOAD_IDLE: */ | |||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
break; | |||||
default: | |||||
goto err; | |||||
} | |||||
break; | |||||
/* case USB_CTRL_REQ_DFU_UPLOAD: */ | |||||
default: | |||||
return (0); | |||||
} | |||||
fail = 0; | |||||
goto out; | |||||
struct dfu_ctx *ctx = data; | |||||
int fail = 1; | |||||
switch ((enum dfu_ctrl_req_code)req->bRequest) { | |||||
case USB_CTRL_REQ_DFU_DNLOAD: { | |||||
void *buf; | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuIDLE: | |||||
ctx->off = 0; | |||||
break; | |||||
case DFU_STATE_dfuDNLOAD_IDLE: | |||||
break; | |||||
default: | |||||
goto err; | |||||
} | |||||
/** | |||||
* XXX we are not allowed to STALL here, and we need to eat all transferred data. | |||||
* better not allow setup_write to break the protocol. | |||||
*/ | |||||
ctx->status = ctx->setup_write(ctx->off, req->wLength, &buf); | |||||
if (ctx->status != DFU_STATUS_OK) { | |||||
ctx->state = DFU_STATE_dfuERROR; | |||||
goto err_have_status; | |||||
} | |||||
if (req->wLength > 0) | |||||
usb_ep0_rx(buf, req->wLength, dfu_dnload_complete, ctx); | |||||
else | |||||
dfu_dnload_complete(NULL, 0, ctx); | |||||
goto out_no_status; | |||||
} | |||||
case USB_CTRL_REQ_DFU_GETSTATUS: { | |||||
struct dfu_status_t st; | |||||
st.bState = ctx->state; | |||||
st.bStatus = ctx->status; | |||||
st.bwPollTimeout = 1000; /* XXX */ | |||||
/** | |||||
* If we're in DFU_STATE_dfuMANIFEST, we just finished | |||||
* the download, and we're just about to send our last | |||||
* status report. Once the report has been sent, go | |||||
* and reset the system to put the new firmware into | |||||
* effect. | |||||
*/ | |||||
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL); | |||||
if (ctx->state == DFU_STATE_dfuMANIFEST) { | |||||
usb_handle_control_status_cb(dfu_reset_system); | |||||
goto out_no_status; | |||||
} | |||||
break; | |||||
} | |||||
case USB_CTRL_REQ_DFU_CLRSTATUS: | |||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
ctx->status = DFU_STATUS_OK; | |||||
break; | |||||
case USB_CTRL_REQ_DFU_GETSTATE: { | |||||
uint8_t st = ctx->state; | |||||
usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL); | |||||
break; | |||||
} | |||||
case USB_CTRL_REQ_DFU_ABORT: | |||||
switch (ctx->state) { | |||||
case DFU_STATE_dfuIDLE: | |||||
case DFU_STATE_dfuDNLOAD_IDLE: | |||||
/* case DFU_STATE_dfuUPLOAD_IDLE: */ | |||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
break; | |||||
default: | |||||
goto err; | |||||
} | |||||
break; | |||||
/* case USB_CTRL_REQ_DFU_UPLOAD: */ | |||||
default: | |||||
return (0); | |||||
} | |||||
fail = 0; | |||||
goto out; | |||||
err: | err: | ||||
ctx->status = DFU_STATUS_errSTALLEDPKT; | |||||
ctx->status = DFU_STATUS_errSTALLEDPKT; | |||||
err_have_status: | err_have_status: | ||||
ctx->state = DFU_STATE_dfuERROR; | |||||
ctx->state = DFU_STATE_dfuERROR; | |||||
out: | out: | ||||
usb_handle_control_status(fail); | |||||
usb_handle_control_status(fail); | |||||
out_no_status: | out_no_status: | ||||
return (1); | |||||
return (1); | |||||
} | } | ||||
void dfu_init( dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx ) | void dfu_init( dfu_setup_write_t setup_write, dfu_finish_write_t finish_write, struct dfu_ctx *ctx ) | ||||
{ | { | ||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
ctx->setup_write = setup_write; | |||||
ctx->finish_write = finish_write; | |||||
usb_attach_function(&dfu_function, &ctx->header); | |||||
ctx->state = DFU_STATE_dfuIDLE; | |||||
ctx->setup_write = setup_write; | |||||
ctx->finish_write = finish_write; | |||||
usb_attach_function(&dfu_function, &ctx->header); | |||||
} | } | ||||
const struct usbd_function dfu_function = { | const struct usbd_function dfu_function = { | ||||
.control = dfu_handle_control, | |||||
.interface_count = USB_FUNCTION_DFU_IFACE_COUNT, | |||||
.control = dfu_handle_control, | |||||
.interface_count = USB_FUNCTION_DFU_IFACE_COUNT, | |||||
}; | }; | ||||
#ifndef USB_DFU_TRANSFER_SIZE | #ifndef USB_DFU_TRANSFER_SIZE | ||||
#define USB_DFU_TRANSFER_SIZE FLASH_SECTOR_SIZE | |||||
#define USB_DFU_TRANSFER_SIZE FLASH_SECTOR_SIZE | |||||
#endif | #endif | ||||
#define USB_FUNCTION_DESC_DFU_DECL \ | #define USB_FUNCTION_DESC_DFU_DECL \ | ||||
struct dfu_function_desc | |||||
struct dfu_function_desc | |||||
#define USB_FUNCTION_DFU_IFACE_COUNT 1 | |||||
#define USB_FUNCTION_DFU_RX_EP_COUNT 0 | |||||
#define USB_FUNCTION_DFU_TX_EP_COUNT 0 | |||||
#define USB_FUNCTION_DFU_IFACE_COUNT 1 | |||||
#define USB_FUNCTION_DFU_RX_EP_COUNT 0 | |||||
#define USB_FUNCTION_DFU_TX_EP_COUNT 0 | |||||
// ----- Macros ----- | // ----- Macros ----- | ||||
#define USB_FUNCTION_DESC_DFU(state...) \ | #define USB_FUNCTION_DESC_DFU(state...) \ | ||||
{ \ | |||||
.iface = { \ | |||||
.bLength = sizeof(struct usb_desc_iface_t), \ | |||||
.bDescriptorType = USB_DESC_IFACE, \ | |||||
.bInterfaceNumber = USB_FUNCTION_IFACE(0, state), \ | |||||
.bAlternateSetting = 0, \ | |||||
.bNumEndpoints = 0, \ | |||||
.bInterfaceClass = USB_DEV_CLASS_APP, \ | |||||
.bInterfaceSubClass = USB_DEV_SUBCLASS_APP_DFU, \ | |||||
.bInterfaceProtocol = USB_DEV_PROTO_DFU_DFU, \ | |||||
.iInterface = 0, \ | |||||
}, \ | |||||
.dfu = { \ | |||||
.bLength = sizeof(struct dfu_desc_functional), \ | |||||
.bDescriptorType = { \ | |||||
.id = 0x1, \ | |||||
.type_type = USB_DESC_TYPE_CLASS \ | |||||
}, \ | |||||
.will_detach = 1, \ | |||||
.manifestation_tolerant = 0, \ | |||||
.can_upload = 0, \ | |||||
.can_download = 1, \ | |||||
.wDetachTimeOut = 0, \ | |||||
.wTransferSize = USB_DFU_TRANSFER_SIZE, \ | |||||
.bcdDFUVersion = { .maj = 1, .min = 1 } \ | |||||
} \ | |||||
} | |||||
{ \ | |||||
.iface = { \ | |||||
.bLength = sizeof(struct usb_desc_iface_t), \ | |||||
.bDescriptorType = USB_DESC_IFACE, \ | |||||
.bInterfaceNumber = USB_FUNCTION_IFACE(0, state), \ | |||||
.bAlternateSetting = 0, \ | |||||
.bNumEndpoints = 0, \ | |||||
.bInterfaceClass = USB_DEV_CLASS_APP, \ | |||||
.bInterfaceSubClass = USB_DEV_SUBCLASS_APP_DFU, \ | |||||
.bInterfaceProtocol = USB_DEV_PROTO_DFU_DFU, \ | |||||
.iInterface = 0, \ | |||||
}, \ | |||||
.dfu = { \ | |||||
.bLength = sizeof(struct dfu_desc_functional), \ | |||||
.bDescriptorType = { \ | |||||
.id = 0x1, \ | |||||
.type_type = USB_DESC_TYPE_CLASS \ | |||||
}, \ | |||||
.will_detach = 1, \ | |||||
.manifestation_tolerant = 0, \ | |||||
.can_upload = 0, \ | |||||
.can_download = 1, \ | |||||
.wDetachTimeOut = 0, \ | |||||
.wTransferSize = USB_DFU_TRANSFER_SIZE, \ | |||||
.bcdDFUVersion = { .maj = 1, .min = 1 } \ | |||||
} \ | |||||
} | |||||
// ----- Enumerations ----- | // ----- Enumerations ----- | ||||
enum dfu_dev_subclass { | enum dfu_dev_subclass { | ||||
USB_DEV_SUBCLASS_APP_DFU = 0x01 | |||||
USB_DEV_SUBCLASS_APP_DFU = 0x01 | |||||
}; | }; | ||||
enum dfu_dev_proto { | enum dfu_dev_proto { | ||||
USB_DEV_PROTO_DFU_APP = 0x01, | |||||
USB_DEV_PROTO_DFU_DFU = 0x02 | |||||
USB_DEV_PROTO_DFU_APP = 0x01, | |||||
USB_DEV_PROTO_DFU_DFU = 0x02 | |||||
}; | }; | ||||
enum dfu_ctrl_req_code { | enum dfu_ctrl_req_code { | ||||
USB_CTRL_REQ_DFU_DETACH = 0, | |||||
USB_CTRL_REQ_DFU_DNLOAD = 1, | |||||
USB_CTRL_REQ_DFU_UPLOAD = 2, | |||||
USB_CTRL_REQ_DFU_GETSTATUS = 3, | |||||
USB_CTRL_REQ_DFU_CLRSTATUS = 4, | |||||
USB_CTRL_REQ_DFU_GETSTATE = 5, | |||||
USB_CTRL_REQ_DFU_ABORT = 6 | |||||
USB_CTRL_REQ_DFU_DETACH = 0, | |||||
USB_CTRL_REQ_DFU_DNLOAD = 1, | |||||
USB_CTRL_REQ_DFU_UPLOAD = 2, | |||||
USB_CTRL_REQ_DFU_GETSTATUS = 3, | |||||
USB_CTRL_REQ_DFU_CLRSTATUS = 4, | |||||
USB_CTRL_REQ_DFU_GETSTATE = 5, | |||||
USB_CTRL_REQ_DFU_ABORT = 6 | |||||
}; | }; | ||||
enum dfu_status { | enum dfu_status { | ||||
DFU_STATUS_async = 0xff, | |||||
DFU_STATUS_OK = 0x00, | |||||
DFU_STATUS_errTARGET = 0x01, | |||||
DFU_STATUS_errFILE = 0x02, | |||||
DFU_STATUS_errWRITE = 0x03, | |||||
DFU_STATUS_errERASE = 0x04, | |||||
DFU_STATUS_errCHECK_ERASED = 0x05, | |||||
DFU_STATUS_errPROG = 0x06, | |||||
DFU_STATUS_errVERIFY = 0x07, | |||||
DFU_STATUS_errADDRESS = 0x08, | |||||
DFU_STATUS_errNOTDONE = 0x09, | |||||
DFU_STATUS_errFIRMWARE = 0x0a, | |||||
DFU_STATUS_errVENDOR = 0x0b, | |||||
DFU_STATUS_errUSBR = 0x0c, | |||||
DFU_STATUS_errPOR = 0x0d, | |||||
DFU_STATUS_errUNKNOWN = 0x0e, | |||||
DFU_STATUS_errSTALLEDPKT = 0x0f | |||||
DFU_STATUS_async = 0xff, | |||||
DFU_STATUS_OK = 0x00, | |||||
DFU_STATUS_errTARGET = 0x01, | |||||
DFU_STATUS_errFILE = 0x02, | |||||
DFU_STATUS_errWRITE = 0x03, | |||||
DFU_STATUS_errERASE = 0x04, | |||||
DFU_STATUS_errCHECK_ERASED = 0x05, | |||||
DFU_STATUS_errPROG = 0x06, | |||||
DFU_STATUS_errVERIFY = 0x07, | |||||
DFU_STATUS_errADDRESS = 0x08, | |||||
DFU_STATUS_errNOTDONE = 0x09, | |||||
DFU_STATUS_errFIRMWARE = 0x0a, | |||||
DFU_STATUS_errVENDOR = 0x0b, | |||||
DFU_STATUS_errUSBR = 0x0c, | |||||
DFU_STATUS_errPOR = 0x0d, | |||||
DFU_STATUS_errUNKNOWN = 0x0e, | |||||
DFU_STATUS_errSTALLEDPKT = 0x0f | |||||
}; | }; | ||||
enum dfu_state { | enum dfu_state { | ||||
DFU_STATE_appIDLE = 0, | |||||
DFU_STATE_appDETACH = 1, | |||||
DFU_STATE_dfuIDLE = 2, | |||||
DFU_STATE_dfuDNLOAD_SYNC = 3, | |||||
DFU_STATE_dfuDNBUSY = 4, | |||||
DFU_STATE_dfuDNLOAD_IDLE = 5, | |||||
DFU_STATE_dfuMANIFEST_SYNC = 6, | |||||
DFU_STATE_dfuMANIFEST = 7, | |||||
DFU_STATE_dfuMANIFEST_WAIT_RESET = 8, | |||||
DFU_STATE_dfuUPLOAD_IDLE = 9, | |||||
DFU_STATE_dfuERROR = 10 | |||||
DFU_STATE_appIDLE = 0, | |||||
DFU_STATE_appDETACH = 1, | |||||
DFU_STATE_dfuIDLE = 2, | |||||
DFU_STATE_dfuDNLOAD_SYNC = 3, | |||||
DFU_STATE_dfuDNBUSY = 4, | |||||
DFU_STATE_dfuDNLOAD_IDLE = 5, | |||||
DFU_STATE_dfuMANIFEST_SYNC = 6, | |||||
DFU_STATE_dfuMANIFEST = 7, | |||||
DFU_STATE_dfuMANIFEST_WAIT_RESET = 8, | |||||
DFU_STATE_dfuUPLOAD_IDLE = 9, | |||||
DFU_STATE_dfuERROR = 10 | |||||
}; | }; | ||||
// ----- Structs ----- | // ----- Structs ----- | ||||
struct dfu_status_t { | struct dfu_status_t { | ||||
enum dfu_status bStatus : 8; | |||||
uint32_t bwPollTimeout : 24; | |||||
enum dfu_state bState : 8; | |||||
uint8_t iString; | |||||
enum dfu_status bStatus : 8; | |||||
uint32_t bwPollTimeout : 24; | |||||
enum dfu_state bState : 8; | |||||
uint8_t iString; | |||||
} __packed; | } __packed; | ||||
CTASSERT_SIZE_BYTE(struct dfu_status_t, 6); | CTASSERT_SIZE_BYTE(struct dfu_status_t, 6); | ||||
typedef void (*dfu_detach_t)(void); | typedef void (*dfu_detach_t)(void); | ||||
struct dfu_ctx { | struct dfu_ctx { | ||||
struct usbd_function_ctx_header header; | |||||
enum dfu_state state; | |||||
enum dfu_status status; | |||||
dfu_setup_write_t setup_write; | |||||
dfu_finish_write_t finish_write; | |||||
size_t off; | |||||
size_t len; | |||||
struct usbd_function_ctx_header header; | |||||
enum dfu_state state; | |||||
enum dfu_status status; | |||||
dfu_setup_write_t setup_write; | |||||
dfu_finish_write_t finish_write; | |||||
size_t off; | |||||
size_t len; | |||||
}; | }; | ||||
struct dfu_desc_functional { | struct dfu_desc_functional { | ||||
uint8_t bLength; | |||||
struct usb_desc_type_t bDescriptorType; /* = class DFU/0x1 FUNCTIONAL */ | |||||
union { | |||||
struct { | |||||
uint8_t can_download : 1; | |||||
uint8_t can_upload : 1; | |||||
uint8_t manifestation_tolerant : 1; | |||||
uint8_t will_detach : 1; | |||||
uint8_t _rsvd0 : 4; | |||||
}; | |||||
uint8_t bmAttributes; | |||||
}; | |||||
uint16_t wDetachTimeOut; | |||||
uint16_t wTransferSize; | |||||
struct usb_bcd_t bcdDFUVersion; | |||||
uint8_t bLength; | |||||
struct usb_desc_type_t bDescriptorType; /* = class DFU/0x1 FUNCTIONAL */ | |||||
union { | |||||
struct { | |||||
uint8_t can_download : 1; | |||||
uint8_t can_upload : 1; | |||||
uint8_t manifestation_tolerant : 1; | |||||
uint8_t will_detach : 1; | |||||
uint8_t _rsvd0 : 4; | |||||
}; | |||||
uint8_t bmAttributes; | |||||
}; | |||||
uint16_t wDetachTimeOut; | |||||
uint16_t wTransferSize; | |||||
struct usb_bcd_t bcdDFUVersion; | |||||
} __packed; | } __packed; | ||||
CTASSERT_SIZE_BYTE(struct dfu_desc_functional, 9); | CTASSERT_SIZE_BYTE(struct dfu_desc_functional, 9); | ||||
struct dfu_function_desc { | struct dfu_function_desc { | ||||
struct usb_desc_iface_t iface; | |||||
struct dfu_desc_functional dfu; | |||||
struct usb_desc_iface_t iface; | |||||
struct dfu_desc_functional dfu; | |||||
}; | }; | ||||
__attribute__((section(".ramtext.ftfl_submit_cmd"), long_call)) | __attribute__((section(".ramtext.ftfl_submit_cmd"), long_call)) | ||||
int ftfl_submit_cmd(void) | int ftfl_submit_cmd(void) | ||||
{ | { | ||||
FTFL.fstat.raw = ((struct FTFL_FSTAT_t){ | |||||
.ccif = 1, | |||||
.rdcolerr = 1, | |||||
.accerr = 1, | |||||
.fpviol = 1 | |||||
}).raw; | |||||
struct FTFL_FSTAT_t stat; | |||||
while (!(stat = FTFL.fstat).ccif) | |||||
/* NOTHING */; /* XXX maybe WFI? */ | |||||
return (!!stat.mgstat0); | |||||
FTFL.fstat.raw = ((struct FTFL_FSTAT_t){ | |||||
.ccif = 1, | |||||
.rdcolerr = 1, | |||||
.accerr = 1, | |||||
.fpviol = 1 | |||||
}).raw; | |||||
struct FTFL_FSTAT_t stat; | |||||
while (!(stat = FTFL.fstat).ccif) | |||||
/* NOTHING */; /* XXX maybe WFI? */ | |||||
return (!!stat.mgstat0); | |||||
} | } | ||||
int flash_prepare_flashing(void) | int flash_prepare_flashing(void) | ||||
{ | { | ||||
/* switch to FlexRAM */ | |||||
if (!FTFL.fcnfg.ramrdy) { | |||||
FTFL.fccob.set_flexram.fcmd = FTFL_FCMD_SET_FLEXRAM; | |||||
FTFL.fccob.set_flexram.flexram_function = FTFL_FLEXRAM_RAM; | |||||
return (ftfl_submit_cmd()); | |||||
} | |||||
return (0); | |||||
/* switch to FlexRAM */ | |||||
if (!FTFL.fcnfg.ramrdy) { | |||||
FTFL.fccob.set_flexram.fcmd = FTFL_FCMD_SET_FLEXRAM; | |||||
FTFL.fccob.set_flexram.flexram_function = FTFL_FLEXRAM_RAM; | |||||
return (ftfl_submit_cmd()); | |||||
} | |||||
return (0); | |||||
} | } | ||||
int flash_erase_sector(uintptr_t addr) | int flash_erase_sector(uintptr_t addr) | ||||
{ | { | ||||
if (addr < (uintptr_t)&_app_rom && | |||||
flash_ALLOW_BRICKABLE_ADDRESSES != 0x00023420) | |||||
return (-1); | |||||
FTFL.fccob.erase.fcmd = FTFL_FCMD_ERASE_SECTOR; | |||||
FTFL.fccob.erase.addr = addr; | |||||
return (ftfl_submit_cmd()); | |||||
if (addr < (uintptr_t)&_app_rom && | |||||
flash_ALLOW_BRICKABLE_ADDRESSES != 0x00023420) | |||||
return (-1); | |||||
FTFL.fccob.erase.fcmd = FTFL_FCMD_ERASE_SECTOR; | |||||
FTFL.fccob.erase.addr = addr; | |||||
return (ftfl_submit_cmd()); | |||||
} | } | ||||
int flash_program_section(uintptr_t addr, size_t num_words) | int flash_program_section(uintptr_t addr, size_t num_words) | ||||
{ | { | ||||
FTFL.fccob.program_section.fcmd = FTFL_FCMD_PROGRAM_SECTION; | |||||
FTFL.fccob.program_section.addr = addr; | |||||
FTFL.fccob.program_section.num_words = num_words; | |||||
return (ftfl_submit_cmd()); | |||||
FTFL.fccob.program_section.fcmd = FTFL_FCMD_PROGRAM_SECTION; | |||||
FTFL.fccob.program_section.addr = addr; | |||||
FTFL.fccob.program_section.num_words = num_words; | |||||
return (ftfl_submit_cmd()); | |||||
} | } | ||||
int flash_program_sector(uintptr_t addr, size_t len) | int flash_program_sector(uintptr_t addr, size_t len) | ||||
{ | { | ||||
return (len != FLASH_SECTOR_SIZE || | |||||
(addr & (FLASH_SECTOR_SIZE - 1)) != 0 || | |||||
flash_erase_sector(addr) || | |||||
flash_program_section(addr, FLASH_SECTOR_SIZE/4)); | |||||
return (len != FLASH_SECTOR_SIZE || | |||||
(addr & (FLASH_SECTOR_SIZE - 1)) != 0 || | |||||
flash_erase_sector(addr) || | |||||
flash_program_section(addr, FLASH_SECTOR_SIZE/4)); | |||||
} | } | ||||
void *flash_get_staging_area(uintptr_t addr, size_t len) | void *flash_get_staging_area(uintptr_t addr, size_t len) | ||||
{ | { | ||||
if ((addr & (FLASH_SECTOR_SIZE - 1)) != 0 || | |||||
len != FLASH_SECTOR_SIZE) | |||||
return (NULL); | |||||
return (FlexRAM); | |||||
if ((addr & (FLASH_SECTOR_SIZE - 1)) != 0 || | |||||
len != FLASH_SECTOR_SIZE) | |||||
return (NULL); | |||||
return (FlexRAM); | |||||
} | } | ||||
// ----- Structs ----- | // ----- Structs ----- | ||||
struct FTFL_FSTAT_t { | struct FTFL_FSTAT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t mgstat0 : 1; | |||||
uint8_t _rsvd0 : 3; | |||||
uint8_t fpviol : 1; | |||||
uint8_t accerr : 1; | |||||
uint8_t rdcolerr : 1; | |||||
uint8_t ccif : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t mgstat0 : 1; | |||||
uint8_t _rsvd0 : 3; | |||||
uint8_t fpviol : 1; | |||||
uint8_t accerr : 1; | |||||
uint8_t rdcolerr : 1; | |||||
uint8_t ccif : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct FTFL_FSTAT_t, 8); | CTASSERT_SIZE_BIT(struct FTFL_FSTAT_t, 8); | ||||
struct FTFL_FCNFG_t { | struct FTFL_FCNFG_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t eeerdy : 1; | |||||
uint8_t ramrdy : 1; | |||||
uint8_t pflsh : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t erssusp : 1; | |||||
uint8_t ersareq : 1; | |||||
uint8_t rdcollie : 1; | |||||
uint8_t ccie : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t eeerdy : 1; | |||||
uint8_t ramrdy : 1; | |||||
uint8_t pflsh : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t erssusp : 1; | |||||
uint8_t ersareq : 1; | |||||
uint8_t rdcollie : 1; | |||||
uint8_t ccie : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct FTFL_FCNFG_t, 8); | CTASSERT_SIZE_BIT(struct FTFL_FCNFG_t, 8); | ||||
struct FTFL_FSEC_t { | struct FTFL_FSEC_t { | ||||
UNION_STRUCT_START(8); | |||||
enum { | |||||
FTFL_FSEC_SEC_UNSECURE = 2, | |||||
FTFL_FSEC_SEC_SECURE = 3 | |||||
} sec : 2; | |||||
enum { | |||||
FTFL_FSEC_FSLACC_DENY = 1, | |||||
FTFL_FSEC_FSLACC_GRANT = 3 | |||||
} fslacc : 2; | |||||
enum { | |||||
FTFL_FSEC_MEEN_DISABLE = 2, | |||||
FTFL_FSEC_MEEN_ENABLE = 3 | |||||
} meen : 2; | |||||
enum { | |||||
FTFL_FSEC_KEYEN_DISABLE = 1, | |||||
FTFL_FSEC_KEYEN_ENABLE = 2 | |||||
} keyen : 2; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
enum { | |||||
FTFL_FSEC_SEC_UNSECURE = 2, | |||||
FTFL_FSEC_SEC_SECURE = 3 | |||||
} sec : 2; | |||||
enum { | |||||
FTFL_FSEC_FSLACC_DENY = 1, | |||||
FTFL_FSEC_FSLACC_GRANT = 3 | |||||
} fslacc : 2; | |||||
enum { | |||||
FTFL_FSEC_MEEN_DISABLE = 2, | |||||
FTFL_FSEC_MEEN_ENABLE = 3 | |||||
} meen : 2; | |||||
enum { | |||||
FTFL_FSEC_KEYEN_DISABLE = 1, | |||||
FTFL_FSEC_KEYEN_ENABLE = 2 | |||||
} keyen : 2; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct FTFL_FSEC_t, 8); | CTASSERT_SIZE_BIT(struct FTFL_FSEC_t, 8); | ||||
struct FTFL_FOPT_t { | struct FTFL_FOPT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t lpboot : 1; | |||||
uint8_t ezport_dis : 1; | |||||
uint8_t nmi_dis : 1; | |||||
uint8_t _rsvd0 : 5; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t lpboot : 1; | |||||
uint8_t ezport_dis : 1; | |||||
uint8_t nmi_dis : 1; | |||||
uint8_t _rsvd0 : 5; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct FTFL_FOPT_t, 8); | CTASSERT_SIZE_BIT(struct FTFL_FOPT_t, 8); | ||||
* some that is little endian. | * some that is little endian. | ||||
*/ | */ | ||||
union FTFL_FCCOB_t { | union FTFL_FCCOB_t { | ||||
struct ftfl_generic { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD { | |||||
FTFL_FCMD_READ_1s_BLOCK = 0x00, | |||||
FTFL_FCMD_READ_1s_SECTION = 0x01, | |||||
FTFL_FCMD_PROGRAM_CHECK = 0x02, | |||||
FTFL_FCMD_READ_RESOURCE = 0x03, | |||||
FTFL_FCMD_PROGRAM_LONGWORD = 0x06, | |||||
FTFL_FCMD_ERASE_BLOCK = 0x08, | |||||
FTFL_FCMD_ERASE_SECTOR = 0x09, | |||||
FTFL_FCMD_PROGRAM_SECTION = 0x0b, | |||||
FTFL_FCMD_READ_1s_ALL_BLOCKS = 0x40, | |||||
FTFL_FCMD_READ_ONCE = 0x41, | |||||
FTFL_FCMD_PROGRAM_ONCE = 0x43, | |||||
FTFL_FCMD_ERASE_ALL_BLOCKS = 0x44, | |||||
FTFL_FCMD_VERIFY_KEY = 0x45, | |||||
FTFL_FCMD_PROGRAM_PARTITION = 0x80, | |||||
FTFL_FCMD_SET_FLEXRAM = 0x81 | |||||
} fcmd : 8; | |||||
uint8_t data_be[8]; | |||||
} generic; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_MARGIN_CHOICE { | |||||
FTFL_MARGIN_NORMAL = 0x00, | |||||
FTFL_MARGIN_USER = 0x01, | |||||
FTFL_MARGIN_FACTORY = 0x02 | |||||
} margin : 8; | |||||
} read_1s_block; | |||||
struct ftfl_data_num_words { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
uint16_t num_words; | |||||
} read_1s_section; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
uint8_t data_be[4]; | |||||
} program_check; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint32_t data; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_RESOURCE_SELECT { | |||||
FTFL_RESOURCE_IFR = 0x00, | |||||
FTFL_RESOURCE_VERSION = 0x01 | |||||
} resource_select : 8; | |||||
} read_resource; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t data_be[4]; | |||||
} program_longword; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} erase; | |||||
struct ftfl_data_num_words program_section; | |||||
struct { | |||||
uint8_t _rsvd0[2]; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} read_1s_all_blocks; | |||||
struct ftfl_cmd_once { | |||||
uint8_t _rsvd0[2]; | |||||
uint8_t idx; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t data_be[4]; | |||||
} read_once; | |||||
struct ftfl_cmd_once program_once; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} erase_all; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t key_be[8]; | |||||
} verify_key; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd1[2]; | |||||
/* the following enum is analogous to enum | |||||
* SIM_FLEXNVM_PARTITION in sim.h, but this one is padded | |||||
* with four 1-bits to make an 8-bit value. | |||||
*/ | |||||
enum FTFL_FLEXNVM_PARTITION { | |||||
FTFL_FLEXNVM_DATA_32_EEPROM_0 = 0xF0, | |||||
FTFL_FLEXNVM_DATA_24_EEPROM_8 = 0xF1, | |||||
FTFL_FLEXNVM_DATA_16_EEPROM_16 = 0xF2, | |||||
FTFL_FLEXNVM_DATA_8_EEPROM_24 = 0xF9, | |||||
FTFL_FLEXNVM_DATA_0_EEPROM_32 = 0xF3 | |||||
} flexnvm_partition : 8; | |||||
enum FTFL_EEPROM_SIZE { | |||||
FTFL_EEPROM_SIZE_0 = 0x3f, | |||||
FTFL_EEPROM_SIZE_32 = 0x39, | |||||
FTFL_EEPROM_SIZE_64 = 0x38, | |||||
FTFL_EEPROM_SIZE_128 = 0x37, | |||||
FTFL_EEPROM_SIZE_256 = 0x36, | |||||
FTFL_EEPROM_SIZE_512 = 0x35, | |||||
FTFL_EEPROM_SIZE_1024 = 0x34, | |||||
FTFL_EEPROM_SIZE_2048 = 0x33 | |||||
} eeprom_size : 8; | |||||
} program_partition; | |||||
struct { | |||||
uint8_t _rsvd0[2]; | |||||
enum FTFL_FLEXRAM_FUNCTION { | |||||
FTFL_FLEXRAM_EEPROM = 0x00, | |||||
FTFL_FLEXRAM_RAM = 0xff | |||||
} flexram_function : 8; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} set_flexram; | |||||
struct ftfl_generic { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD { | |||||
FTFL_FCMD_READ_1s_BLOCK = 0x00, | |||||
FTFL_FCMD_READ_1s_SECTION = 0x01, | |||||
FTFL_FCMD_PROGRAM_CHECK = 0x02, | |||||
FTFL_FCMD_READ_RESOURCE = 0x03, | |||||
FTFL_FCMD_PROGRAM_LONGWORD = 0x06, | |||||
FTFL_FCMD_ERASE_BLOCK = 0x08, | |||||
FTFL_FCMD_ERASE_SECTOR = 0x09, | |||||
FTFL_FCMD_PROGRAM_SECTION = 0x0b, | |||||
FTFL_FCMD_READ_1s_ALL_BLOCKS = 0x40, | |||||
FTFL_FCMD_READ_ONCE = 0x41, | |||||
FTFL_FCMD_PROGRAM_ONCE = 0x43, | |||||
FTFL_FCMD_ERASE_ALL_BLOCKS = 0x44, | |||||
FTFL_FCMD_VERIFY_KEY = 0x45, | |||||
FTFL_FCMD_PROGRAM_PARTITION = 0x80, | |||||
FTFL_FCMD_SET_FLEXRAM = 0x81 | |||||
} fcmd : 8; | |||||
uint8_t data_be[8]; | |||||
} generic; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_MARGIN_CHOICE { | |||||
FTFL_MARGIN_NORMAL = 0x00, | |||||
FTFL_MARGIN_USER = 0x01, | |||||
FTFL_MARGIN_FACTORY = 0x02 | |||||
} margin : 8; | |||||
} read_1s_block; | |||||
struct ftfl_data_num_words { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
uint16_t num_words; | |||||
} read_1s_section; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
uint8_t data_be[4]; | |||||
} program_check; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint32_t data; | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_RESOURCE_SELECT { | |||||
FTFL_RESOURCE_IFR = 0x00, | |||||
FTFL_RESOURCE_VERSION = 0x01 | |||||
} resource_select : 8; | |||||
} read_resource; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t data_be[4]; | |||||
} program_longword; | |||||
struct { | |||||
uint32_t addr : 24; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} erase; | |||||
struct ftfl_data_num_words program_section; | |||||
struct { | |||||
uint8_t _rsvd0[2]; | |||||
enum FTFL_MARGIN_CHOICE margin : 8; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} read_1s_all_blocks; | |||||
struct ftfl_cmd_once { | |||||
uint8_t _rsvd0[2]; | |||||
uint8_t idx; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t data_be[4]; | |||||
} read_once; | |||||
struct ftfl_cmd_once program_once; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} erase_all; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t key_be[8]; | |||||
} verify_key; | |||||
struct { | |||||
uint8_t _rsvd0[3]; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
uint8_t _rsvd1[2]; | |||||
/* the following enum is analogous to enum | |||||
* SIM_FLEXNVM_PARTITION in sim.h, but this one is padded | |||||
* with four 1-bits to make an 8-bit value. | |||||
*/ | |||||
enum FTFL_FLEXNVM_PARTITION { | |||||
FTFL_FLEXNVM_DATA_32_EEPROM_0 = 0xF0, | |||||
FTFL_FLEXNVM_DATA_24_EEPROM_8 = 0xF1, | |||||
FTFL_FLEXNVM_DATA_16_EEPROM_16 = 0xF2, | |||||
FTFL_FLEXNVM_DATA_8_EEPROM_24 = 0xF9, | |||||
FTFL_FLEXNVM_DATA_0_EEPROM_32 = 0xF3 | |||||
} flexnvm_partition : 8; | |||||
enum FTFL_EEPROM_SIZE { | |||||
FTFL_EEPROM_SIZE_0 = 0x3f, | |||||
FTFL_EEPROM_SIZE_32 = 0x39, | |||||
FTFL_EEPROM_SIZE_64 = 0x38, | |||||
FTFL_EEPROM_SIZE_128 = 0x37, | |||||
FTFL_EEPROM_SIZE_256 = 0x36, | |||||
FTFL_EEPROM_SIZE_512 = 0x35, | |||||
FTFL_EEPROM_SIZE_1024 = 0x34, | |||||
FTFL_EEPROM_SIZE_2048 = 0x33 | |||||
} eeprom_size : 8; | |||||
} program_partition; | |||||
struct { | |||||
uint8_t _rsvd0[2]; | |||||
enum FTFL_FLEXRAM_FUNCTION { | |||||
FTFL_FLEXRAM_EEPROM = 0x00, | |||||
FTFL_FLEXRAM_RAM = 0xff | |||||
} flexram_function : 8; | |||||
enum FTFL_FCMD fcmd : 8; | |||||
} set_flexram; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(union FTFL_FCCOB_t, 12); | CTASSERT_SIZE_BYTE(union FTFL_FCCOB_t, 12); | ||||
struct FTFL_t { | struct FTFL_t { | ||||
struct FTFL_FSTAT_t fstat; | |||||
struct FTFL_FCNFG_t fcnfg; | |||||
struct FTFL_FSEC_t fsec; | |||||
struct FTFL_FOPT_t fopt; | |||||
union FTFL_FCCOB_t fccob; | |||||
uint8_t fprot_be[4]; | |||||
uint8_t feprot; | |||||
uint8_t fdprot; | |||||
struct FTFL_FSTAT_t fstat; | |||||
struct FTFL_FCNFG_t fcnfg; | |||||
struct FTFL_FSEC_t fsec; | |||||
struct FTFL_FOPT_t fopt; | |||||
union FTFL_FCCOB_t fccob; | |||||
uint8_t fprot_be[4]; | |||||
uint8_t feprot; | |||||
uint8_t fdprot; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct FTFL_t, 0x18); | CTASSERT_SIZE_BYTE(struct FTFL_t, 0x18); | ||||
/* Flash Configuration Field, see Sub-Family Reference Manual, section 28.3.1 */ | /* Flash Configuration Field, see Sub-Family Reference Manual, section 28.3.1 */ | ||||
struct FTFL_CONFIG_t { | struct FTFL_CONFIG_t { | ||||
uint8_t key[8]; | |||||
uint8_t fprot[4]; | |||||
struct FTFL_FSEC_t fsec; | |||||
struct FTFL_FOPT_t fopt; | |||||
uint8_t feprot; | |||||
uint8_t fdprot; | |||||
uint8_t key[8]; | |||||
uint8_t fprot[4]; | |||||
struct FTFL_FSEC_t fsec; | |||||
struct FTFL_FOPT_t fopt; | |||||
uint8_t feprot; | |||||
uint8_t fdprot; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct FTFL_CONFIG_t, 16); | CTASSERT_SIZE_BYTE(struct FTFL_CONFIG_t, 16); | ||||
static struct USB_BD_t * | static struct USB_BD_t * | ||||
usb_get_bd(struct usbd_ep_pipe_state_t *s) | usb_get_bd(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]); | |||||
return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]); | |||||
} | } | ||||
static struct USB_BD_t * | static struct USB_BD_t * | ||||
usb_get_bd_stat(struct USB_STAT_t *stat) | usb_get_bd_stat(struct USB_STAT_t *stat) | ||||
{ | { | ||||
return (((void *)(uintptr_t)bdt + (stat->raw << 1))); | |||||
return (((void *)(uintptr_t)bdt + (stat->raw << 1))); | |||||
} | } | ||||
void *usb_get_xfer_data(struct usb_xfer_info *i) | void *usb_get_xfer_data(struct usb_xfer_info *i) | ||||
{ | { | ||||
return (usb_get_bd_stat(i)->addr); | |||||
return (usb_get_bd_stat(i)->addr); | |||||
} | } | ||||
enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *i) | enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *i) | ||||
{ | { | ||||
return (usb_get_bd_stat(i)->tok_pid); | |||||
return (usb_get_bd_stat(i)->tok_pid); | |||||
} | } | ||||
int usb_get_xfer_ep(struct usb_xfer_info *i) | int usb_get_xfer_ep(struct usb_xfer_info *i) | ||||
{ | { | ||||
return (i->ep); | |||||
return (i->ep); | |||||
} | } | ||||
enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *i) | enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *i) | ||||
{ | { | ||||
return (i->dir); | |||||
return (i->dir); | |||||
} | } | ||||
void usb_enable_xfers(void) | void usb_enable_xfers(void) | ||||
{ | { | ||||
USB0.ctl.raw = ((struct USB_CTL_t){ | |||||
.txd_suspend = 0, | |||||
.usben = 1 | |||||
}).raw; | |||||
USB0.ctl.raw = ((struct USB_CTL_t){ | |||||
.txd_suspend = 0, | |||||
.usben = 1 | |||||
}).raw; | |||||
} | } | ||||
void usb_set_addr(int addr) | void usb_set_addr(int addr) | ||||
{ | { | ||||
USB0.addr.raw = addr; | |||||
USB0.addr.raw = addr; | |||||
} | } | ||||
void usb_pipe_stall(struct usbd_ep_pipe_state_t *s) | void usb_pipe_stall(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
bd->raw = ((struct USB_BD_BITS_t){ | |||||
.stall = 1, | |||||
.own = 1 | |||||
}).raw; | |||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
bd->raw = ((struct USB_BD_BITS_t){ | |||||
.stall = 1, | |||||
.own = 1 | |||||
}).raw; | |||||
} | } | ||||
void usb_pipe_unstall(struct usbd_ep_pipe_state_t *s) | void usb_pipe_unstall(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
struct USB_BD_BITS_t state = { .raw = bd->raw }; | |||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
struct USB_BD_BITS_t state = { .raw = bd->raw }; | |||||
if (state.own && state.stall) | |||||
bd->raw = 0; | |||||
if (state.own && state.stall) | |||||
bd->raw = 0; | |||||
} | } | ||||
void usb_pipe_enable(struct usbd_ep_pipe_state_t *s) | void usb_pipe_enable(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){ | |||||
.eptxen = s->ep_dir == USB_EP_TX, | |||||
.eprxen = s->ep_dir == USB_EP_RX, | |||||
.ephshk = 1, /* XXX ISO */ | |||||
.epctldis = s->ep_num != 0 | |||||
}).raw; | |||||
USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){ | |||||
.eptxen = s->ep_dir == USB_EP_TX, | |||||
.eprxen = s->ep_dir == USB_EP_RX, | |||||
.ephshk = 1, /* XXX ISO */ | |||||
.epctldis = s->ep_num != 0 | |||||
}).raw; | |||||
} | } | ||||
void usb_pipe_disable(struct usbd_ep_pipe_state_t *s) | void usb_pipe_disable(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){ | |||||
.eptxen = s->ep_dir == USB_EP_TX, | |||||
.eprxen = s->ep_dir == USB_EP_RX, | |||||
.epctldis = 1 | |||||
}).raw; | |||||
USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){ | |||||
.eptxen = s->ep_dir == USB_EP_TX, | |||||
.eprxen = s->ep_dir == USB_EP_RX, | |||||
.epctldis = 1 | |||||
}).raw; | |||||
} | } | ||||
size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *s) | size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *s) | ||||
{ | { | ||||
struct USB_BD_t *bd = usb_get_bd(s); | |||||
return (bd->bc); | |||||
struct USB_BD_t *bd = usb_get_bd(s); | |||||
return (bd->bc); | |||||
} | } | ||||
void usb_queue_next(struct usbd_ep_pipe_state_t *s, void *addr, size_t len) | void usb_queue_next(struct usbd_ep_pipe_state_t *s, void *addr, size_t len) | ||||
{ | { | ||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
bd->addr = addr; | |||||
/* damn you bitfield problems */ | |||||
bd->raw = ((struct USB_BD_BITS_t){ | |||||
.dts = 1, | |||||
.own = 1, | |||||
.data01 = s->data01, | |||||
.bc = len, | |||||
}).raw; | |||||
volatile struct USB_BD_t *bd = usb_get_bd(s); | |||||
bd->addr = addr; | |||||
/* damn you bitfield problems */ | |||||
bd->raw = ((struct USB_BD_BITS_t){ | |||||
.dts = 1, | |||||
.own = 1, | |||||
.data01 = s->data01, | |||||
.bc = len, | |||||
}).raw; | |||||
} | } | ||||
static void usb_reset(void) | static void usb_reset(void) | ||||
{ | { | ||||
/* reset pingpong state */ | |||||
/* For some obscure reason, we need to use or here. */ | |||||
USB0.ctl.raw |= ((struct USB_CTL_t){ | |||||
.txd_suspend = 1, | |||||
.oddrst = 1, | |||||
}).raw; | |||||
/* clear all interrupt bits - not sure if needed */ | |||||
USB0.istat.raw = 0xff; | |||||
USB0.errstat.raw = 0xff; | |||||
USB0.otgistat.raw = 0xff; | |||||
/* zap also BDT pingpong & queued transactions */ | |||||
memset(bdt, 0, sizeof(bdt)); | |||||
USB0.addr.raw = 0; | |||||
usb_restart(); | |||||
USB0.ctl.raw = ((struct USB_CTL_t){ | |||||
.txd_suspend = 0, | |||||
.usben = 1 | |||||
}).raw; | |||||
/* we're only interested in reset and transfers */ | |||||
USB0.inten.raw = ((struct USB_ISTAT_t){ | |||||
.tokdne = 1, | |||||
.usbrst = 1, | |||||
.stall = 1, | |||||
.sleep = 1, | |||||
}).raw; | |||||
USB0.usbtrc0.usbresmen = 0; | |||||
USB0.usbctrl.susp = 0; | |||||
/* reset pingpong state */ | |||||
/* For some obscure reason, we need to use or here. */ | |||||
USB0.ctl.raw |= ((struct USB_CTL_t){ | |||||
.txd_suspend = 1, | |||||
.oddrst = 1, | |||||
}).raw; | |||||
/* clear all interrupt bits - not sure if needed */ | |||||
USB0.istat.raw = 0xff; | |||||
USB0.errstat.raw = 0xff; | |||||
USB0.otgistat.raw = 0xff; | |||||
/* zap also BDT pingpong & queued transactions */ | |||||
memset(bdt, 0, sizeof(bdt)); | |||||
USB0.addr.raw = 0; | |||||
usb_restart(); | |||||
USB0.ctl.raw = ((struct USB_CTL_t){ | |||||
.txd_suspend = 0, | |||||
.usben = 1 | |||||
}).raw; | |||||
/* we're only interested in reset and transfers */ | |||||
USB0.inten.raw = ((struct USB_ISTAT_t){ | |||||
.tokdne = 1, | |||||
.usbrst = 1, | |||||
.stall = 1, | |||||
.sleep = 1, | |||||
}).raw; | |||||
USB0.usbtrc0.usbresmen = 0; | |||||
USB0.usbctrl.susp = 0; | |||||
} | } | ||||
void usb_enable(void) | void usb_enable(void) | ||||
{ | { | ||||
SIM.sopt2.usbsrc = 1; /* usb from mcg */ | |||||
SIM.scgc4.usbotg = 1; /* enable usb clock */ | |||||
/* reset module - not sure if needed */ | |||||
USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){ | |||||
.usbreset = 1, | |||||
.usbresmen = 1 | |||||
}).raw; | |||||
while (USB0.usbtrc0.usbreset) | |||||
/* NOTHING */; | |||||
USB0.bdtpage1 = (uintptr_t)bdt >> 8; | |||||
USB0.bdtpage2 = (uintptr_t)bdt >> 16; | |||||
USB0.bdtpage3 = (uintptr_t)bdt >> 24; | |||||
USB0.control.raw = ((struct USB_CONTROL_t){ | |||||
.dppullupnonotg = 1 /* enable pullup */ | |||||
}).raw; | |||||
USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */ | |||||
usb_reset(); /* this will start usb processing */ | |||||
/* really only one thing we want */ | |||||
USB0.inten.raw = ((struct USB_ISTAT_t){ | |||||
.usbrst = 1, | |||||
}).raw; | |||||
/** | |||||
* Suspend transceiver now - we'll wake up at reset again. | |||||
*/ | |||||
SIM.sopt2.usbsrc = 1; /* usb from mcg */ | |||||
SIM.scgc4.usbotg = 1; /* enable usb clock */ | |||||
/* reset module - not sure if needed */ | |||||
USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){ | |||||
.usbreset = 1, | |||||
.usbresmen = 1 | |||||
}).raw; | |||||
while (USB0.usbtrc0.usbreset) | |||||
/* NOTHING */; | |||||
USB0.bdtpage1 = (uintptr_t)bdt >> 8; | |||||
USB0.bdtpage2 = (uintptr_t)bdt >> 16; | |||||
USB0.bdtpage3 = (uintptr_t)bdt >> 24; | |||||
USB0.control.raw = ((struct USB_CONTROL_t){ | |||||
.dppullupnonotg = 1 /* enable pullup */ | |||||
}).raw; | |||||
USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */ | |||||
usb_reset(); /* this will start usb processing */ | |||||
/* really only one thing we want */ | |||||
USB0.inten.raw = ((struct USB_ISTAT_t){ | |||||
.usbrst = 1, | |||||
}).raw; | |||||
/** | |||||
* Suspend transceiver now - we'll wake up at reset again. | |||||
*/ | |||||
// TODO - Possible removal | // TODO - Possible removal | ||||
USB0.usbctrl.susp = 1; | |||||
USB0.usbtrc0.usbresmen = 1; | |||||
USB0.usbctrl.susp = 1; | |||||
USB0.usbtrc0.usbresmen = 1; | |||||
} | } | ||||
void USB0_Handler(void) | void USB0_Handler(void) | ||||
{ | { | ||||
struct USB_ISTAT_t stat = {.raw = USB0.istat.raw }; | |||||
if (stat.usbrst) { | |||||
usb_reset(); | |||||
return; | |||||
} | |||||
if (stat.stall) { | |||||
/* XXX need more work for non-0 ep */ | |||||
volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx); | |||||
if (bd->stall) | |||||
usb_setup_control(); | |||||
} | |||||
if (stat.tokdne) { | |||||
struct usb_xfer_info stat = USB0.stat; | |||||
usb_handle_transaction(&stat); | |||||
} | |||||
if (stat.sleep) { | |||||
USB0.inten.sleep = 0; | |||||
USB0.inten.resume = 1; | |||||
USB0.usbctrl.susp = 1; | |||||
USB0.usbtrc0.usbresmen = 1; | |||||
/** | |||||
* Clear interrupts now so that we can detect a fresh | |||||
* resume later on. | |||||
*/ | |||||
USB0.istat.raw = stat.raw; | |||||
const struct usbd_config *c = usb_get_config_data(-1); | |||||
if (c && c->suspend) | |||||
c->suspend(); | |||||
} | |||||
/** | |||||
* XXX it is unclear whether we will receive a synchronous | |||||
* resume interrupt if we were in sleep. This code assumes we | |||||
* do. | |||||
*/ | |||||
if (stat.resume || USB0.usbtrc0.usb_resume_int) { | |||||
USB0.inten.resume = 0; | |||||
USB0.inten.sleep = 1; | |||||
USB0.usbtrc0.usbresmen = 0; | |||||
USB0.usbctrl.susp = 0; | |||||
const struct usbd_config *c = usb_get_config_data(-1); | |||||
if (c && c->resume) | |||||
c->resume(); | |||||
stat.resume = 1; /* always clear bit */ | |||||
} | |||||
USB0.istat.raw = stat.raw; | |||||
struct USB_ISTAT_t stat = {.raw = USB0.istat.raw }; | |||||
if (stat.usbrst) { | |||||
usb_reset(); | |||||
return; | |||||
} | |||||
if (stat.stall) { | |||||
/* XXX need more work for non-0 ep */ | |||||
volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx); | |||||
if (bd->stall) | |||||
usb_setup_control(); | |||||
} | |||||
if (stat.tokdne) { | |||||
struct usb_xfer_info stat = USB0.stat; | |||||
usb_handle_transaction(&stat); | |||||
} | |||||
if (stat.sleep) { | |||||
USB0.inten.sleep = 0; | |||||
USB0.inten.resume = 1; | |||||
USB0.usbctrl.susp = 1; | |||||
USB0.usbtrc0.usbresmen = 1; | |||||
/** | |||||
* Clear interrupts now so that we can detect a fresh | |||||
* resume later on. | |||||
*/ | |||||
USB0.istat.raw = stat.raw; | |||||
const struct usbd_config *c = usb_get_config_data(-1); | |||||
if (c && c->suspend) | |||||
c->suspend(); | |||||
} | |||||
/** | |||||
* XXX it is unclear whether we will receive a synchronous | |||||
* resume interrupt if we were in sleep. This code assumes we | |||||
* do. | |||||
*/ | |||||
if (stat.resume || USB0.usbtrc0.usb_resume_int) { | |||||
USB0.inten.resume = 0; | |||||
USB0.inten.sleep = 1; | |||||
USB0.usbtrc0.usbresmen = 0; | |||||
USB0.usbctrl.susp = 0; | |||||
const struct usbd_config *c = usb_get_config_data(-1); | |||||
if (c && c->resume) | |||||
c->resume(); | |||||
stat.resume = 1; /* always clear bit */ | |||||
} | |||||
USB0.istat.raw = stat.raw; | |||||
} | } | ||||
void usb_poll(void) | void usb_poll(void) | ||||
{ | { | ||||
USB0_Handler(); | |||||
USB0_Handler(); | |||||
} | } | ||||
int usb_tx_serialno(size_t reqlen) | int usb_tx_serialno(size_t reqlen) | ||||
{ | { | ||||
struct usb_desc_string_t *d; | |||||
const size_t nregs = 3; | |||||
/** | |||||
* actually 4, but UIDH is 0xffffffff. Also our output buffer | |||||
* is only 64 bytes, and 128 bit + desc header exceeds this by | |||||
* 2 bytes. | |||||
*/ | |||||
const size_t len = nregs * 4 * 2 * 2 + sizeof(*d); | |||||
d = usb_ep0_tx_inplace_prepare(len); | |||||
if (d == NULL) | |||||
return (-1); | |||||
d->bLength = len; | |||||
d->bDescriptorType = USB_DESC_STRING; | |||||
size_t bufpos = 0; | |||||
for (size_t reg = 0; reg < nregs; ++reg) { | |||||
/* registers run MSW first */ | |||||
uint32_t val = (&SIM.uidmh)[reg]; | |||||
for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) { | |||||
int nibble = val >> 28; | |||||
if (nibble > 9) | |||||
nibble += 'a' - '9' - 1; | |||||
((char16_t *)d->bString)[bufpos++] = nibble + '0'; | |||||
} | |||||
} | |||||
usb_ep0_tx(d, len, reqlen, NULL, NULL); | |||||
return (0); | |||||
struct usb_desc_string_t *d; | |||||
const size_t nregs = 3; | |||||
/** | |||||
* actually 4, but UIDH is 0xffffffff. Also our output buffer | |||||
* is only 64 bytes, and 128 bit + desc header exceeds this by | |||||
* 2 bytes. | |||||
*/ | |||||
const size_t len = nregs * 4 * 2 * 2 + sizeof(*d); | |||||
d = usb_ep0_tx_inplace_prepare(len); | |||||
if (d == NULL) | |||||
return (-1); | |||||
d->bLength = len; | |||||
d->bDescriptorType = USB_DESC_STRING; | |||||
size_t bufpos = 0; | |||||
for (size_t reg = 0; reg < nregs; ++reg) { | |||||
/* registers run MSW first */ | |||||
uint32_t val = (&SIM.uidmh)[reg]; | |||||
for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) { | |||||
int nibble = val >> 28; | |||||
if (nibble > 9) | |||||
nibble += 'a' - '9' - 1; | |||||
((char16_t *)d->bString)[bufpos++] = nibble + '0'; | |||||
} | |||||
} | |||||
usb_ep0_tx(d, len, reqlen, NULL, NULL); | |||||
return (0); | |||||
} | } | ||||
static enum dfu_status setup_write(size_t off, size_t len, void **buf) | static enum dfu_status setup_write(size_t off, size_t len, void **buf) | ||||
{ | { | ||||
static int last = 0; | |||||
if (len > sizeof(staging)) | |||||
return (DFU_STATUS_errADDRESS); | |||||
// We only allow the last write to be less than one sector size. | |||||
if (off == 0) | |||||
last = 0; | |||||
if (last && len != 0) | |||||
return (DFU_STATUS_errADDRESS); | |||||
if (len != FLASH_SECTOR_SIZE) { | |||||
last = 1; | |||||
memset(staging, 0xff, sizeof(staging)); | |||||
} | |||||
*buf = staging; | |||||
return (DFU_STATUS_OK); | |||||
static int last = 0; | |||||
if (len > sizeof(staging)) | |||||
return (DFU_STATUS_errADDRESS); | |||||
// We only allow the last write to be less than one sector size. | |||||
if (off == 0) | |||||
last = 0; | |||||
if (last && len != 0) | |||||
return (DFU_STATUS_errADDRESS); | |||||
if (len != FLASH_SECTOR_SIZE) { | |||||
last = 1; | |||||
memset(staging, 0xff, sizeof(staging)); | |||||
} | |||||
*buf = staging; | |||||
return (DFU_STATUS_OK); | |||||
} | } | ||||
static enum dfu_status finish_write( void *buf, size_t off, size_t len ) | static enum dfu_status finish_write( void *buf, size_t off, size_t len ) | ||||
{ | { | ||||
void *target; | |||||
if (len == 0) | |||||
return (DFU_STATUS_OK); | |||||
target = flash_get_staging_area(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE); | |||||
if (!target) | |||||
return (DFU_STATUS_errADDRESS); | |||||
memcpy(target, buf, len); | |||||
if (flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) != 0) | |||||
return (DFU_STATUS_errADDRESS); | |||||
return (DFU_STATUS_OK); | |||||
void *target; | |||||
if (len == 0) | |||||
return (DFU_STATUS_OK); | |||||
target = flash_get_staging_area(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE); | |||||
if (!target) | |||||
return (DFU_STATUS_errADDRESS); | |||||
memcpy(target, buf, len); | |||||
if (flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) != 0) | |||||
return (DFU_STATUS_errADDRESS); | |||||
return (DFU_STATUS_OK); | |||||
} | } | ||||
void init_usb_bootloader( int config ) | void init_usb_bootloader( int config ) | ||||
{ | { | ||||
dfu_init(setup_write, finish_write, &dfu_ctx); | |||||
dfu_init(setup_write, finish_write, &dfu_ctx); | |||||
} | } | ||||
void main() | void main() | ||||
#endif | #endif | ||||
flash_prepare_flashing(); | |||||
flash_prepare_flashing(); | |||||
usb_init( &dfu_device ); | |||||
for (;;) | |||||
usb_init( &dfu_device ); | |||||
for (;;) | |||||
{ | { | ||||
usb_poll(); | |||||
} | |||||
usb_poll(); | |||||
} | |||||
} | } | ||||
#define CTASSERT_SIZE_BIT(t, s) CTASSERT(sizeof(t) * 8 == (s)) | #define CTASSERT_SIZE_BIT(t, s) CTASSERT(sizeof(t) * 8 == (s)) | ||||
#define UNION_STRUCT_START(size) \ | #define UNION_STRUCT_START(size) \ | ||||
union { \ | |||||
_CONCAT(_CONCAT(uint, size), _t) raw; \ | |||||
struct { \ | |||||
/* just to swallow the following semicolon */ \ | |||||
struct _CONCAT(_CONCAT(__dummy_, __COUNTER__), _t) {} | |||||
union { \ | |||||
_CONCAT(_CONCAT(uint, size), _t) raw; \ | |||||
struct { \ | |||||
/* just to swallow the following semicolon */ \ | |||||
struct _CONCAT(_CONCAT(__dummy_, __COUNTER__), _t) {} | |||||
#define UNION_STRUCT_END \ | #define UNION_STRUCT_END \ | ||||
}; /* struct */ \ | |||||
}; /* union */ | |||||
}; /* struct */ \ | |||||
}; /* union */ | |||||
/** | /** | ||||
* <https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s> | * <https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s> | ||||
*/ | */ | ||||
#define __PP_NARG(...) \ | #define __PP_NARG(...) \ | ||||
__PP_NARG_(__0, ## __VA_ARGS__, __PP_RSEQ_N()) | |||||
__PP_NARG_(__0, ## __VA_ARGS__, __PP_RSEQ_N()) | |||||
#define __PP_NARG_(...) \ | #define __PP_NARG_(...) \ | ||||
__PP_ARG_N(__VA_ARGS__) | |||||
__PP_ARG_N(__VA_ARGS__) | |||||
#define __PP_ARG_N( \ | #define __PP_ARG_N( \ | ||||
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ | |||||
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ | |||||
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ | |||||
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ | |||||
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ | |||||
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ | |||||
_61,_62,_63,N,...) N | |||||
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ | |||||
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ | |||||
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ | |||||
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ | |||||
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ | |||||
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ | |||||
_61,_62,_63,N,...) N | |||||
#define __PP_RSEQ_N() \ | #define __PP_RSEQ_N() \ | ||||
62,61,60, \ | |||||
59,58,57,56,55,54,53,52,51,50, \ | |||||
49,48,47,46,45,44,43,42,41,40, \ | |||||
39,38,37,36,35,34,33,32,31,30, \ | |||||
29,28,27,26,25,24,23,22,21,20, \ | |||||
19,18,17,16,15,14,13,12,11,10, \ | |||||
9,8,7,6,5,4,3,2,1,0 | |||||
62,61,60, \ | |||||
59,58,57,56,55,54,53,52,51,50, \ | |||||
49,48,47,46,45,44,43,42,41,40, \ | |||||
39,38,37,36,35,34,33,32,31,30, \ | |||||
29,28,27,26,25,24,23,22,21,20, \ | |||||
19,18,17,16,15,14,13,12,11,10, \ | |||||
9,8,7,6,5,4,3,2,1,0 | |||||
/** | /** | ||||
* From <https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms> | * From <https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms> | ||||
#define __REPEAT_INNER(...) __OBSTRUCT(__REPEAT_INDIRECT) () (__VA_ARGS__) | #define __REPEAT_INNER(...) __OBSTRUCT(__REPEAT_INDIRECT) () (__VA_ARGS__) | ||||
#define __REPEAT_INDIRECT() __REPEAT_ | #define __REPEAT_INDIRECT() __REPEAT_ | ||||
#define __REPEAT_(iter, itermacro, macro, a, ...) \ | #define __REPEAT_(iter, itermacro, macro, a, ...) \ | ||||
__OBSTRUCT(macro)(iter, a) \ | |||||
__WHEN(__PP_NARG(__VA_ARGS__)) \ | |||||
( \ | |||||
__OBSTRUCT(__REPEAT_INDIRECT) () ( \ | |||||
itermacro(iter, a), itermacro, macro, __VA_ARGS__ \ | |||||
) \ | |||||
) | |||||
__OBSTRUCT(macro)(iter, a) \ | |||||
__WHEN(__PP_NARG(__VA_ARGS__)) \ | |||||
( \ | |||||
__OBSTRUCT(__REPEAT_INDIRECT) () ( \ | |||||
itermacro(iter, a), itermacro, macro, __VA_ARGS__ \ | |||||
) \ | |||||
) | |||||
#endif | #endif | ||||
// ----- Structs ----- | // ----- Structs ----- | ||||
struct SIM_t { | struct SIM_t { | ||||
struct SIM_SOPT1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 12; | |||||
enum { | |||||
SIM_RAMSIZE_8KB = 1, | |||||
SIM_RAMSIZE_16KB = 3 | |||||
} ramsize : 4; | |||||
uint32_t _rsvd1 : 2; | |||||
enum { | |||||
SIM_OSC32KSEL_SYSTEM = 0, | |||||
SIM_OSC32KSEL_RTC = 2, | |||||
SIM_OSC32KSEL_LPO = 3 | |||||
} osc32ksel : 2; | |||||
uint32_t _rsvd2 : 9; | |||||
uint32_t usbvstby : 1; | |||||
uint32_t usbsstby : 1; | |||||
uint32_t usbregen : 1; | |||||
UNION_STRUCT_END; | |||||
} sopt1; | |||||
struct SIM_SOPT1CFG_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 24; | |||||
uint32_t urwe : 1; | |||||
uint32_t uvswe : 1; | |||||
uint32_t usswe : 1; | |||||
uint32_t _rsvd1 : 5; | |||||
UNION_STRUCT_END; | |||||
} sopt1cfg; | |||||
uint32_t _pad0[(0x1004 - 0x8) / 4]; | |||||
struct SIM_SOPT2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 4; | |||||
enum { | |||||
SIM_RTCCLKOUTSEL_1HZ = 0, | |||||
SIM_RTCCLKOUTSEL_32KHZ = 1 | |||||
} rtcclkoutsel : 1; | |||||
enum { | |||||
SIM_CLKOUTSEL_FLASH = 2, | |||||
SIM_CLKOUTSEL_LPO = 3, | |||||
SIM_CLKOUTSEL_MCG = 4, | |||||
SIM_CLKOUTSEL_RTC = 5, | |||||
SIM_CLKOUTSEL_OSC = 6 | |||||
} clkoutsel : 3; | |||||
uint32_t _rsvd1 : 3; | |||||
enum { | |||||
SIM_PTD7PAD_SINGLE = 0, | |||||
SIM_PTD7PAD_DOUBLE = 1 | |||||
} ptd7pad : 1; | |||||
enum { | |||||
SIM_TRACECLKSEL_MCG = 0, | |||||
SIM_TRACECLKSEL_CORE = 1 | |||||
} traceclksel : 1; | |||||
uint32_t _rsvd2 : 3; | |||||
enum { | |||||
SIM_PLLFLLSEL_FLL = 0, | |||||
SIM_PLLFLLSEL_PLL = 1 | |||||
} pllfllsel : 1; | |||||
uint32_t _rsvd3 : 1; | |||||
enum { | |||||
SIM_USBSRC_EXTERNAL = 0, | |||||
SIM_USBSRC_MCG = 1 | |||||
} usbsrc : 1; | |||||
uint32_t _rsvd4 : 13; | |||||
UNION_STRUCT_END; | |||||
} sopt2; | |||||
uint32_t _pad1; | |||||
struct SIM_SOPT4_t { | |||||
UNION_STRUCT_START(32); | |||||
enum sim_ftmflt { | |||||
SIM_FTMFLT_FTM = 0, | |||||
SIM_FTMFLT_CMP = 1 | |||||
} ftm0flt0 : 1; | |||||
enum sim_ftmflt ftm0flt1 : 1; | |||||
uint32_t _rsvd0 : 2; | |||||
enum sim_ftmflt ftm1flt0 : 1; | |||||
uint32_t _rsvd1 : 13; | |||||
enum { | |||||
SIM_FTMCHSRC_FTM = 0, | |||||
SIM_FTMCHSRC_CMP0 = 1, | |||||
SIM_FTMCHSRC_CMP1 = 2, | |||||
SIM_FTMCHSRC_USBSOF = 3 | |||||
} ftm1ch0src : 2; | |||||
uint32_t _rsvd2 : 4; | |||||
enum sim_ftmclksel { | |||||
SIM_FTMCLKSEL_CLK0 = 0, | |||||
SIM_FTMCLKSEL_CLK1 = 1 | |||||
} ftm0clksel : 1; | |||||
enum sim_ftmclksel ftm1clksel : 1; | |||||
uint32_t _rsvd3 : 2; | |||||
enum { | |||||
SIM_FTMTRGSRC_HSCMP0 = 0, | |||||
SIM_FTMTRGSRC_FTM1 = 1 | |||||
} ftm0trg0src : 1; | |||||
uint32_t _rsvd4 : 3; | |||||
UNION_STRUCT_END; | |||||
} sopt4; | |||||
struct SIM_SOPT5_t { | |||||
UNION_STRUCT_START(32); | |||||
enum sim_uarttxsrc { | |||||
SIM_UARTTXSRC_UART = 0, | |||||
SIM_UARTTXSRC_FTM = 1 | |||||
} uart0txsrc : 1; | |||||
uint32_t _rsvd0 : 1; | |||||
enum sim_uartrxsrc { | |||||
SIM_UARTRXSRC_UART = 0, | |||||
SIM_UARTRXSRC_CMP0 = 1, | |||||
SIM_UARTRXSRC_CMP1 = 2 | |||||
} uart0rxsrc : 2; | |||||
enum sim_uarttxsrc uart1txsrc : 1; | |||||
uint32_t _rsvd1 : 1; | |||||
enum sim_uartrxsrc uart1rxsrc : 2; | |||||
uint32_t _rsvd2 : 24; | |||||
UNION_STRUCT_END; | |||||
} sopt5; | |||||
uint32_t _pad2; | |||||
struct SIM_SOPT7_t { | |||||
UNION_STRUCT_START(32); | |||||
enum { | |||||
SIM_ADCTRGSEL_PDB = 0, | |||||
SIM_ADCTRGSEL_HSCMP0 = 1, | |||||
SIM_ADCTRGSEL_HSCMP1 = 2, | |||||
SIM_ADCTRGSEL_PIT0 = 4, | |||||
SIM_ADCTRGSEL_PIT1 = 5, | |||||
SIM_ADCTRGSEL_PIT2 = 6, | |||||
SIM_ADCTRGSEL_PIT3 = 7, | |||||
SIM_ADCTRGSEL_FTM0 = 8, | |||||
SIM_ADCTRGSEL_FTM1 = 9, | |||||
SIM_ADCTRGSEL_RTCALARM = 12, | |||||
SIM_ADCTRGSEL_RTCSECS = 13, | |||||
SIM_ADCTRGSEL_LPTIMER = 14 | |||||
} adc0trgsel : 4; | |||||
enum { | |||||
SIM_ADCPRETRGSEL_A = 0, | |||||
SIM_ADCPRETRGSEL_B = 1 | |||||
} adc0pretrgsel : 1; | |||||
uint32_t _rsvd0 : 2; | |||||
enum { | |||||
SIM_ADCALTTRGEN_PDB = 0, | |||||
SIM_ADCALTTRGEN_ALT = 1 | |||||
} adc0alttrgen : 1; | |||||
uint32_t _rsvd1 : 24; | |||||
UNION_STRUCT_END; | |||||
} sopt7; | |||||
uint32_t _pad3[(0x1024 - 0x101c) / 4]; | |||||
struct SIM_SDID_t { | |||||
UNION_STRUCT_START(32); | |||||
enum { | |||||
SIM_PINID_32 = 2, | |||||
SIM_PINID_48 = 4, | |||||
SIM_PINID_64 = 5 | |||||
} pinid : 4; | |||||
enum { | |||||
SIM_FAMID_K10 = 0, | |||||
SIM_FAMID_K20 = 1 | |||||
} famid : 3; | |||||
uint32_t _rsvd1 : 5; | |||||
uint32_t revid : 4; | |||||
uint32_t _rsvd2 : 16; | |||||
UNION_STRUCT_END; | |||||
} sdid; | |||||
uint32_t _pad4[(0x1034 - 0x1028) / 4]; | |||||
struct SIM_SCGC4_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 1; | |||||
uint32_t ewm : 1; | |||||
uint32_t cmt : 1; | |||||
uint32_t _rsvd1 : 3; | |||||
uint32_t i2c0 : 1; | |||||
uint32_t _rsvd2 : 3; | |||||
uint32_t uart0 : 1; | |||||
uint32_t uart1 : 1; | |||||
uint32_t uart2 : 1; | |||||
uint32_t _rsvd3 : 5; | |||||
uint32_t usbotg : 1; | |||||
uint32_t cmp : 1; | |||||
uint32_t vref : 1; | |||||
uint32_t _rsvd4 : 11; | |||||
UNION_STRUCT_END; | |||||
} scgc4; | |||||
struct SIM_SCGC5_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t lptimer : 1; | |||||
uint32_t _rsvd0 : 4; | |||||
uint32_t tsi : 1; | |||||
uint32_t _rsvd1 : 3; | |||||
uint32_t porta : 1; | |||||
uint32_t portb : 1; | |||||
uint32_t portc : 1; | |||||
uint32_t portd : 1; | |||||
uint32_t porte : 1; | |||||
uint32_t _rsvd2 : 18; | |||||
UNION_STRUCT_END; | |||||
} scgc5; | |||||
struct SIM_SCGC6_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t ftfl : 1; | |||||
uint32_t dmamux : 1; | |||||
uint32_t _rsvd0 : 10; | |||||
uint32_t spi0 : 1; | |||||
uint32_t _rsvd1 : 2; | |||||
uint32_t i2s : 1; | |||||
uint32_t _rsvd2 : 2; | |||||
uint32_t crc : 1; | |||||
uint32_t _rsvd3 : 2; | |||||
uint32_t usbdcd : 1; | |||||
uint32_t pdb : 1; | |||||
uint32_t pit : 1; | |||||
uint32_t ftm0 : 1; | |||||
uint32_t ftm1 : 1; | |||||
uint32_t _rsvd4 : 1; | |||||
uint32_t adc0 : 1; | |||||
uint32_t _rsvd5 : 1; | |||||
uint32_t rtc : 1; | |||||
uint32_t _rsvd6 : 2; | |||||
UNION_STRUCT_END; | |||||
} scgc6; | |||||
struct SIM_SCGC7_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 1; | |||||
uint32_t dma : 1; | |||||
uint32_t _rsvd1 : 30; | |||||
UNION_STRUCT_END; | |||||
} scgc7; | |||||
struct SIM_CLKDIV1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 16; | |||||
uint32_t outdiv4 : 4; | |||||
uint32_t _rsvd1 : 4; | |||||
uint32_t outdiv2 : 4; | |||||
uint32_t outdiv1 : 4; | |||||
UNION_STRUCT_END; | |||||
} clkdiv1; | |||||
struct SIM_CLKDIV2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t usbfrac : 1; | |||||
uint32_t usbdiv : 3; | |||||
uint32_t _rsvd0 : 28; | |||||
UNION_STRUCT_END; | |||||
} clkdiv2; | |||||
struct SIM_FCFG1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t flashdis : 1; | |||||
uint32_t flashdoze : 1; | |||||
uint32_t _rsvd0 : 6; | |||||
struct SIM_SOPT1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 12; | |||||
enum { | |||||
SIM_RAMSIZE_8KB = 1, | |||||
SIM_RAMSIZE_16KB = 3 | |||||
} ramsize : 4; | |||||
uint32_t _rsvd1 : 2; | |||||
enum { | |||||
SIM_OSC32KSEL_SYSTEM = 0, | |||||
SIM_OSC32KSEL_RTC = 2, | |||||
SIM_OSC32KSEL_LPO = 3 | |||||
} osc32ksel : 2; | |||||
uint32_t _rsvd2 : 9; | |||||
uint32_t usbvstby : 1; | |||||
uint32_t usbsstby : 1; | |||||
uint32_t usbregen : 1; | |||||
UNION_STRUCT_END; | |||||
} sopt1; | |||||
struct SIM_SOPT1CFG_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 24; | |||||
uint32_t urwe : 1; | |||||
uint32_t uvswe : 1; | |||||
uint32_t usswe : 1; | |||||
uint32_t _rsvd1 : 5; | |||||
UNION_STRUCT_END; | |||||
} sopt1cfg; | |||||
uint32_t _pad0[(0x1004 - 0x8) / 4]; | |||||
struct SIM_SOPT2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 4; | |||||
enum { | |||||
SIM_RTCCLKOUTSEL_1HZ = 0, | |||||
SIM_RTCCLKOUTSEL_32KHZ = 1 | |||||
} rtcclkoutsel : 1; | |||||
enum { | |||||
SIM_CLKOUTSEL_FLASH = 2, | |||||
SIM_CLKOUTSEL_LPO = 3, | |||||
SIM_CLKOUTSEL_MCG = 4, | |||||
SIM_CLKOUTSEL_RTC = 5, | |||||
SIM_CLKOUTSEL_OSC = 6 | |||||
} clkoutsel : 3; | |||||
uint32_t _rsvd1 : 3; | |||||
enum { | |||||
SIM_PTD7PAD_SINGLE = 0, | |||||
SIM_PTD7PAD_DOUBLE = 1 | |||||
} ptd7pad : 1; | |||||
enum { | |||||
SIM_TRACECLKSEL_MCG = 0, | |||||
SIM_TRACECLKSEL_CORE = 1 | |||||
} traceclksel : 1; | |||||
uint32_t _rsvd2 : 3; | |||||
enum { | |||||
SIM_PLLFLLSEL_FLL = 0, | |||||
SIM_PLLFLLSEL_PLL = 1 | |||||
} pllfllsel : 1; | |||||
uint32_t _rsvd3 : 1; | |||||
enum { | |||||
SIM_USBSRC_EXTERNAL = 0, | |||||
SIM_USBSRC_MCG = 1 | |||||
} usbsrc : 1; | |||||
uint32_t _rsvd4 : 13; | |||||
UNION_STRUCT_END; | |||||
} sopt2; | |||||
uint32_t _pad1; | |||||
struct SIM_SOPT4_t { | |||||
UNION_STRUCT_START(32); | |||||
enum sim_ftmflt { | |||||
SIM_FTMFLT_FTM = 0, | |||||
SIM_FTMFLT_CMP = 1 | |||||
} ftm0flt0 : 1; | |||||
enum sim_ftmflt ftm0flt1 : 1; | |||||
uint32_t _rsvd0 : 2; | |||||
enum sim_ftmflt ftm1flt0 : 1; | |||||
uint32_t _rsvd1 : 13; | |||||
enum { | |||||
SIM_FTMCHSRC_FTM = 0, | |||||
SIM_FTMCHSRC_CMP0 = 1, | |||||
SIM_FTMCHSRC_CMP1 = 2, | |||||
SIM_FTMCHSRC_USBSOF = 3 | |||||
} ftm1ch0src : 2; | |||||
uint32_t _rsvd2 : 4; | |||||
enum sim_ftmclksel { | |||||
SIM_FTMCLKSEL_CLK0 = 0, | |||||
SIM_FTMCLKSEL_CLK1 = 1 | |||||
} ftm0clksel : 1; | |||||
enum sim_ftmclksel ftm1clksel : 1; | |||||
uint32_t _rsvd3 : 2; | |||||
enum { | |||||
SIM_FTMTRGSRC_HSCMP0 = 0, | |||||
SIM_FTMTRGSRC_FTM1 = 1 | |||||
} ftm0trg0src : 1; | |||||
uint32_t _rsvd4 : 3; | |||||
UNION_STRUCT_END; | |||||
} sopt4; | |||||
struct SIM_SOPT5_t { | |||||
UNION_STRUCT_START(32); | |||||
enum sim_uarttxsrc { | |||||
SIM_UARTTXSRC_UART = 0, | |||||
SIM_UARTTXSRC_FTM = 1 | |||||
} uart0txsrc : 1; | |||||
uint32_t _rsvd0 : 1; | |||||
enum sim_uartrxsrc { | |||||
SIM_UARTRXSRC_UART = 0, | |||||
SIM_UARTRXSRC_CMP0 = 1, | |||||
SIM_UARTRXSRC_CMP1 = 2 | |||||
} uart0rxsrc : 2; | |||||
enum sim_uarttxsrc uart1txsrc : 1; | |||||
uint32_t _rsvd1 : 1; | |||||
enum sim_uartrxsrc uart1rxsrc : 2; | |||||
uint32_t _rsvd2 : 24; | |||||
UNION_STRUCT_END; | |||||
} sopt5; | |||||
uint32_t _pad2; | |||||
struct SIM_SOPT7_t { | |||||
UNION_STRUCT_START(32); | |||||
enum { | |||||
SIM_ADCTRGSEL_PDB = 0, | |||||
SIM_ADCTRGSEL_HSCMP0 = 1, | |||||
SIM_ADCTRGSEL_HSCMP1 = 2, | |||||
SIM_ADCTRGSEL_PIT0 = 4, | |||||
SIM_ADCTRGSEL_PIT1 = 5, | |||||
SIM_ADCTRGSEL_PIT2 = 6, | |||||
SIM_ADCTRGSEL_PIT3 = 7, | |||||
SIM_ADCTRGSEL_FTM0 = 8, | |||||
SIM_ADCTRGSEL_FTM1 = 9, | |||||
SIM_ADCTRGSEL_RTCALARM = 12, | |||||
SIM_ADCTRGSEL_RTCSECS = 13, | |||||
SIM_ADCTRGSEL_LPTIMER = 14 | |||||
} adc0trgsel : 4; | |||||
enum { | |||||
SIM_ADCPRETRGSEL_A = 0, | |||||
SIM_ADCPRETRGSEL_B = 1 | |||||
} adc0pretrgsel : 1; | |||||
uint32_t _rsvd0 : 2; | |||||
enum { | |||||
SIM_ADCALTTRGEN_PDB = 0, | |||||
SIM_ADCALTTRGEN_ALT = 1 | |||||
} adc0alttrgen : 1; | |||||
uint32_t _rsvd1 : 24; | |||||
UNION_STRUCT_END; | |||||
} sopt7; | |||||
uint32_t _pad3[(0x1024 - 0x101c) / 4]; | |||||
struct SIM_SDID_t { | |||||
UNION_STRUCT_START(32); | |||||
enum { | |||||
SIM_PINID_32 = 2, | |||||
SIM_PINID_48 = 4, | |||||
SIM_PINID_64 = 5 | |||||
} pinid : 4; | |||||
enum { | |||||
SIM_FAMID_K10 = 0, | |||||
SIM_FAMID_K20 = 1 | |||||
} famid : 3; | |||||
uint32_t _rsvd1 : 5; | |||||
uint32_t revid : 4; | |||||
uint32_t _rsvd2 : 16; | |||||
UNION_STRUCT_END; | |||||
} sdid; | |||||
uint32_t _pad4[(0x1034 - 0x1028) / 4]; | |||||
struct SIM_SCGC4_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 1; | |||||
uint32_t ewm : 1; | |||||
uint32_t cmt : 1; | |||||
uint32_t _rsvd1 : 3; | |||||
uint32_t i2c0 : 1; | |||||
uint32_t _rsvd2 : 3; | |||||
uint32_t uart0 : 1; | |||||
uint32_t uart1 : 1; | |||||
uint32_t uart2 : 1; | |||||
uint32_t _rsvd3 : 5; | |||||
uint32_t usbotg : 1; | |||||
uint32_t cmp : 1; | |||||
uint32_t vref : 1; | |||||
uint32_t _rsvd4 : 11; | |||||
UNION_STRUCT_END; | |||||
} scgc4; | |||||
struct SIM_SCGC5_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t lptimer : 1; | |||||
uint32_t _rsvd0 : 4; | |||||
uint32_t tsi : 1; | |||||
uint32_t _rsvd1 : 3; | |||||
uint32_t porta : 1; | |||||
uint32_t portb : 1; | |||||
uint32_t portc : 1; | |||||
uint32_t portd : 1; | |||||
uint32_t porte : 1; | |||||
uint32_t _rsvd2 : 18; | |||||
UNION_STRUCT_END; | |||||
} scgc5; | |||||
struct SIM_SCGC6_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t ftfl : 1; | |||||
uint32_t dmamux : 1; | |||||
uint32_t _rsvd0 : 10; | |||||
uint32_t spi0 : 1; | |||||
uint32_t _rsvd1 : 2; | |||||
uint32_t i2s : 1; | |||||
uint32_t _rsvd2 : 2; | |||||
uint32_t crc : 1; | |||||
uint32_t _rsvd3 : 2; | |||||
uint32_t usbdcd : 1; | |||||
uint32_t pdb : 1; | |||||
uint32_t pit : 1; | |||||
uint32_t ftm0 : 1; | |||||
uint32_t ftm1 : 1; | |||||
uint32_t _rsvd4 : 1; | |||||
uint32_t adc0 : 1; | |||||
uint32_t _rsvd5 : 1; | |||||
uint32_t rtc : 1; | |||||
uint32_t _rsvd6 : 2; | |||||
UNION_STRUCT_END; | |||||
} scgc6; | |||||
struct SIM_SCGC7_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 1; | |||||
uint32_t dma : 1; | |||||
uint32_t _rsvd1 : 30; | |||||
UNION_STRUCT_END; | |||||
} scgc7; | |||||
struct SIM_CLKDIV1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 16; | |||||
uint32_t outdiv4 : 4; | |||||
uint32_t _rsvd1 : 4; | |||||
uint32_t outdiv2 : 4; | |||||
uint32_t outdiv1 : 4; | |||||
UNION_STRUCT_END; | |||||
} clkdiv1; | |||||
struct SIM_CLKDIV2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t usbfrac : 1; | |||||
uint32_t usbdiv : 3; | |||||
uint32_t _rsvd0 : 28; | |||||
UNION_STRUCT_END; | |||||
} clkdiv2; | |||||
struct SIM_FCFG1_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t flashdis : 1; | |||||
uint32_t flashdoze : 1; | |||||
uint32_t _rsvd0 : 6; | |||||
/* the following enum is analogous to enum | |||||
* FTFL_FLEXNVM_PARTITION in ftfl.h, but that one is padded | |||||
* with four 1-bits to make an 8-bit value. | |||||
*/ | |||||
enum SIM_FLEXNVM_PARTITION { | |||||
SIM_FLEXNVM_DATA_32_EEPROM_0 = 0x0, | |||||
SIM_FLEXNVM_DATA_24_EEPROM_8 = 0x1, | |||||
SIM_FLEXNVM_DATA_16_EEPROM_16 = 0x2, | |||||
SIM_FLEXNVM_DATA_8_EEPROM_24 = 0x9, | |||||
SIM_FLEXNVM_DATA_0_EEPROM_32 = 0x3 | |||||
} depart : 4; | |||||
/* the following enum is analogous to enum | |||||
* FTFL_FLEXNVM_PARTITION in ftfl.h, but that one is padded | |||||
* with four 1-bits to make an 8-bit value. | |||||
*/ | |||||
enum SIM_FLEXNVM_PARTITION { | |||||
SIM_FLEXNVM_DATA_32_EEPROM_0 = 0x0, | |||||
SIM_FLEXNVM_DATA_24_EEPROM_8 = 0x1, | |||||
SIM_FLEXNVM_DATA_16_EEPROM_16 = 0x2, | |||||
SIM_FLEXNVM_DATA_8_EEPROM_24 = 0x9, | |||||
SIM_FLEXNVM_DATA_0_EEPROM_32 = 0x3 | |||||
} depart : 4; | |||||
uint32_t _rsvd1 : 4; | |||||
enum { | |||||
SIM_EESIZE_2KB = 3, | |||||
SIM_EESIZE_1KB = 4, | |||||
SIM_EESIZE_512B = 5, | |||||
SIM_EESIZE_256B = 6, | |||||
SIM_EESIZE_128B = 7, | |||||
SIM_EESIZE_64B = 8, | |||||
SIM_EESIZE_32B = 9, | |||||
SIM_EESIZE_0B = 15 | |||||
} eesize : 4; | |||||
uint32_t _rsvd2 : 4; | |||||
enum { | |||||
SIM_PFSIZE_32KB = 3, | |||||
SIM_PFSIZE_64KB = 5, | |||||
SIM_PFSIZE_128KB = 7 | |||||
} pfsize : 4; | |||||
enum { | |||||
SIM_NVMSIZE_0KB = 0, | |||||
SIM_NVMSIZE_32KB = 3 | |||||
} nvmsize : 4; | |||||
UNION_STRUCT_END; | |||||
} fcfg1; | |||||
struct SIM_FCFG2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 16; | |||||
uint32_t maxaddr1 : 7; | |||||
enum { | |||||
SIM_PFLSH_FLEXNVM = 0, | |||||
SIM_PFLSH_PROGRAM = 1 | |||||
} pflsh : 1; | |||||
uint32_t maxaddr0 : 7; | |||||
uint32_t _rsvd1 : 1; | |||||
UNION_STRUCT_END; | |||||
} fcfg2; | |||||
uint32_t uidh; | |||||
uint32_t uidmh; | |||||
uint32_t uidml; | |||||
uint32_t uidl; | |||||
uint32_t _rsvd1 : 4; | |||||
enum { | |||||
SIM_EESIZE_2KB = 3, | |||||
SIM_EESIZE_1KB = 4, | |||||
SIM_EESIZE_512B = 5, | |||||
SIM_EESIZE_256B = 6, | |||||
SIM_EESIZE_128B = 7, | |||||
SIM_EESIZE_64B = 8, | |||||
SIM_EESIZE_32B = 9, | |||||
SIM_EESIZE_0B = 15 | |||||
} eesize : 4; | |||||
uint32_t _rsvd2 : 4; | |||||
enum { | |||||
SIM_PFSIZE_32KB = 3, | |||||
SIM_PFSIZE_64KB = 5, | |||||
SIM_PFSIZE_128KB = 7 | |||||
} pfsize : 4; | |||||
enum { | |||||
SIM_NVMSIZE_0KB = 0, | |||||
SIM_NVMSIZE_32KB = 3 | |||||
} nvmsize : 4; | |||||
UNION_STRUCT_END; | |||||
} fcfg1; | |||||
struct SIM_FCFG2_t { | |||||
UNION_STRUCT_START(32); | |||||
uint32_t _rsvd0 : 16; | |||||
uint32_t maxaddr1 : 7; | |||||
enum { | |||||
SIM_PFLSH_FLEXNVM = 0, | |||||
SIM_PFLSH_PROGRAM = 1 | |||||
} pflsh : 1; | |||||
uint32_t maxaddr0 : 7; | |||||
uint32_t _rsvd1 : 1; | |||||
UNION_STRUCT_END; | |||||
} fcfg2; | |||||
uint32_t uidh; | |||||
uint32_t uidmh; | |||||
uint32_t uidml; | |||||
uint32_t uidl; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct SIM_t, 0x1064); | CTASSERT_SIZE_BYTE(struct SIM_t, 0x1064); | ||||
*/ | */ | ||||
size_t nextlen = s->transfer_size; | size_t nextlen = s->transfer_size; | ||||
if (nextlen > s->ep_maxsize) | |||||
nextlen = s->ep_maxsize; | |||||
if (nextlen > s->ep_maxsize) | |||||
nextlen = s->ep_maxsize; | |||||
void *addr = s->data_buf + s->pos; | |||||
void *addr = s->data_buf + s->pos; | |||||
usb_queue_next(s, addr, nextlen); | usb_queue_next(s, addr, nextlen); | ||||
return (1); | return (1); |
#define USB_CTRL_REQ_TYPE_SHIFT 1 | #define USB_CTRL_REQ_TYPE_SHIFT 1 | ||||
#define USB_CTRL_REQ_RECP_SHIFT 3 | #define USB_CTRL_REQ_RECP_SHIFT 3 | ||||
#define USB_CTRL_REQ_CODE_SHIFT 8 | #define USB_CTRL_REQ_CODE_SHIFT 8 | ||||
#define USB_CTRL_REQ(req_inout, req_type, req_code) \ | |||||
(uint16_t) \ | |||||
((USB_CTRL_REQ_##req_inout << USB_CTRL_REQ_DIR_SHIFT) \ | |||||
|(USB_CTRL_REQ_##req_type << USB_CTRL_REQ_TYPE_SHIFT) \ | |||||
#define USB_CTRL_REQ(req_inout, req_type, req_code) \ | |||||
(uint16_t) \ | |||||
((USB_CTRL_REQ_##req_inout << USB_CTRL_REQ_DIR_SHIFT) \ | |||||
|(USB_CTRL_REQ_##req_type << USB_CTRL_REQ_TYPE_SHIFT) \ | |||||
|(USB_CTRL_REQ_##req_code << USB_CTRL_REQ_CODE_SHIFT)) | |(USB_CTRL_REQ_##req_code << USB_CTRL_REQ_CODE_SHIFT)) | ||||
// ----- Macros ----- | // ----- Macros ----- | ||||
#define USB_DESC_STRING(s) \ | |||||
(const void *)&(const struct { \ | |||||
struct usb_desc_string_t dsc; \ | |||||
char16_t str[sizeof(s) / 2 - 1]; \ | |||||
}) {{ \ | |||||
.bLength = sizeof(struct usb_desc_string_t) + \ | |||||
sizeof(s) - 2, \ | |||||
.bDescriptorType = USB_DESC_STRING, \ | |||||
}, \ | |||||
s \ | |||||
#define USB_DESC_STRING(s) \ | |||||
(const void *)&(const struct { \ | |||||
struct usb_desc_string_t dsc; \ | |||||
char16_t str[sizeof(s) / 2 - 1]; \ | |||||
}) {{ \ | |||||
.bLength = sizeof(struct usb_desc_string_t) + \ | |||||
sizeof(s) - 2, \ | |||||
.bDescriptorType = USB_DESC_STRING, \ | |||||
}, \ | |||||
s \ | |||||
} | } | ||||
#define USB_DESC_STRING_LANG_ENUS USB_DESC_STRING(u"\x0409") | #define USB_DESC_STRING_LANG_ENUS USB_DESC_STRING(u"\x0409") | ||||
#define USB_DESC_STRING_SERIALNO ((const void *)1) | #define USB_DESC_STRING_SERIALNO ((const void *)1) | ||||
#define USB_FUNCTION_IFACE(iface, iface_off, tx_ep_off, rx_ep_off) \ | |||||
#define USB_FUNCTION_IFACE(iface, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((iface_off) + (iface)) | ((iface_off) + (iface)) | ||||
#define USB_FUNCTION_TX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
#define USB_FUNCTION_TX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((tx_ep_off) + (ep)) | ((tx_ep_off) + (ep)) | ||||
#define USB_FUNCTION_RX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
#define USB_FUNCTION_RX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((rx_ep_off) + (ep)) | ((rx_ep_off) + (ep)) | ||||
#define USB__INCREMENT(i, _0) (i + 1) | #define USB__INCREMENT(i, _0) (i + 1) | ||||
#define USB__COUNT_IFACE_EP(i, e) \ | |||||
#define USB__COUNT_IFACE_EP(i, e) \ | |||||
__DEFER(USB__COUNT_IFACE_EP_)(__EXPAND i, e) | __DEFER(USB__COUNT_IFACE_EP_)(__EXPAND i, e) | ||||
#define USB__COUNT_IFACE_EP_(iface, tx_ep, rx_ep, func) \ | #define USB__COUNT_IFACE_EP_(iface, tx_ep, rx_ep, func) \ | ||||
(iface + USB_FUNCTION_ ## func ## _IFACE_COUNT, \ | |||||
tx_ep + USB_FUNCTION_ ## func ## _TX_EP_COUNT, \ | |||||
(iface + USB_FUNCTION_ ## func ## _IFACE_COUNT, \ | |||||
tx_ep + USB_FUNCTION_ ## func ## _TX_EP_COUNT, \ | |||||
rx_ep + USB_FUNCTION_ ## func ## _RX_EP_COUNT) | rx_ep + USB_FUNCTION_ ## func ## _RX_EP_COUNT) | ||||
#define USB__GET_FUNCTION_IFACE_COUNT(iter, func) \ | |||||
#define USB__GET_FUNCTION_IFACE_COUNT(iter, func) \ | |||||
USB_FUNCTION_ ## func ## _IFACE_COUNT + | USB_FUNCTION_ ## func ## _IFACE_COUNT + | ||||
#define USB__DEFINE_FUNCTION_DESC(iter, func) \ | |||||
#define USB__DEFINE_FUNCTION_DESC(iter, func) \ | |||||
USB_FUNCTION_DESC_ ## func ## _DECL __CAT(__usb_func_desc, __COUNTER__); | USB_FUNCTION_DESC_ ## func ## _DECL __CAT(__usb_func_desc, __COUNTER__); | ||||
#define USB__INIT_FUNCTION_DESC(iter, func) \ | |||||
#define USB__INIT_FUNCTION_DESC(iter, func) \ | |||||
USB_FUNCTION_DESC_ ## func iter, | USB_FUNCTION_DESC_ ## func iter, | ||||
#define USB__DEFINE_CONFIG_DESC(confignum, name, ...) \ | |||||
&((const struct name { \ | |||||
struct usb_desc_config_t config; \ | |||||
#define USB__DEFINE_CONFIG_DESC(confignum, name, ...) \ | |||||
&((const struct name { \ | |||||
struct usb_desc_config_t config; \ | |||||
__REPEAT_INNER(, __EAT, USB__DEFINE_FUNCTION_DESC, __VA_ARGS__) \ | __REPEAT_INNER(, __EAT, USB__DEFINE_FUNCTION_DESC, __VA_ARGS__) \ | ||||
}){ \ | |||||
.config = { \ | |||||
.bLength = sizeof(struct usb_desc_config_t), \ | |||||
.bDescriptorType = USB_DESC_CONFIG, \ | |||||
.wTotalLength = sizeof(struct name), \ | |||||
}){ \ | |||||
.config = { \ | |||||
.bLength = sizeof(struct usb_desc_config_t), \ | |||||
.bDescriptorType = USB_DESC_CONFIG, \ | |||||
.wTotalLength = sizeof(struct name), \ | |||||
.bNumInterfaces = __REPEAT_INNER(, __EAT, USB__GET_FUNCTION_IFACE_COUNT, __VA_ARGS__) 0, \ | .bNumInterfaces = __REPEAT_INNER(, __EAT, USB__GET_FUNCTION_IFACE_COUNT, __VA_ARGS__) 0, \ | ||||
.bConfigurationValue = confignum, \ | |||||
.iConfiguration = 0, \ | |||||
.one = 1, \ | |||||
.bMaxPower = 50 \ | |||||
}, \ | |||||
.bConfigurationValue = confignum, \ | |||||
.iConfiguration = 0, \ | |||||
.one = 1, \ | |||||
.bMaxPower = 50 \ | |||||
}, \ | |||||
__REPEAT_INNER((0, 0, 0), USB__COUNT_IFACE_EP, USB__INIT_FUNCTION_DESC, __VA_ARGS__) \ | __REPEAT_INNER((0, 0, 0), USB__COUNT_IFACE_EP, USB__INIT_FUNCTION_DESC, __VA_ARGS__) \ | ||||
}).config | }).config | ||||
#define USB__DEFINE_CONFIG(iter, args) \ | |||||
#define USB__DEFINE_CONFIG(iter, args) \ | |||||
__DEFER(USB__DEFINE_CONFIG_)(iter, __EXPAND args) | __DEFER(USB__DEFINE_CONFIG_)(iter, __EXPAND args) | ||||
#define USB__DEFINE_CONFIG_(confignum, initfun, ...) \ | |||||
&(const struct usbd_config){ \ | |||||
.init = initfun, \ | |||||
.desc = USB__DEFINE_CONFIG_DESC( \ | |||||
confignum, \ | |||||
__CAT(__usb_desc, __COUNTER__), \ | |||||
__VA_ARGS__) \ | |||||
#define USB__DEFINE_CONFIG_(confignum, initfun, ...) \ | |||||
&(const struct usbd_config){ \ | |||||
.init = initfun, \ | |||||
.desc = USB__DEFINE_CONFIG_DESC( \ | |||||
confignum, \ | |||||
__CAT(__usb_desc, __COUNTER__), \ | |||||
__VA_ARGS__) \ | |||||
}, | }, | ||||
#define USB_INIT_DEVICE(vid, pid, manuf, product, ...) \ | |||||
{ \ | |||||
.dev_desc = &(const struct usb_desc_dev_t){ \ | |||||
.bLength = sizeof(struct usb_desc_dev_t), \ | |||||
.bDescriptorType = USB_DESC_DEV, \ | |||||
.bcdUSB = { .maj = 2 }, \ | |||||
.bDeviceClass = USB_DEV_CLASS_SEE_IFACE, \ | |||||
.bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE, \ | |||||
.bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE, \ | |||||
.bMaxPacketSize0 = EP0_BUFSIZE, \ | |||||
.idVendor = vid, \ | |||||
.idProduct = pid, \ | |||||
.bcdDevice = { .raw = 0 }, \ | |||||
.iManufacturer = 1, \ | |||||
.iProduct = 2, \ | |||||
.iSerialNumber = 3, \ | |||||
.bNumConfigurations = __PP_NARG(__VA_ARGS__), \ | |||||
}, \ | |||||
#define USB_INIT_DEVICE(vid, pid, manuf, product, ...) \ | |||||
{ \ | |||||
.dev_desc = &(const struct usb_desc_dev_t){ \ | |||||
.bLength = sizeof(struct usb_desc_dev_t), \ | |||||
.bDescriptorType = USB_DESC_DEV, \ | |||||
.bcdUSB = { .maj = 2 }, \ | |||||
.bDeviceClass = USB_DEV_CLASS_SEE_IFACE, \ | |||||
.bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE, \ | |||||
.bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE, \ | |||||
.bMaxPacketSize0 = EP0_BUFSIZE, \ | |||||
.idVendor = vid, \ | |||||
.idProduct = pid, \ | |||||
.bcdDevice = { .raw = 0 }, \ | |||||
.iManufacturer = 1, \ | |||||
.iProduct = 2, \ | |||||
.iSerialNumber = 3, \ | |||||
.bNumConfigurations = __PP_NARG(__VA_ARGS__), \ | |||||
}, \ | |||||
.string_descs = (const struct usb_desc_string_t * const []){ \ | .string_descs = (const struct usb_desc_string_t * const []){ \ | ||||
USB_DESC_STRING_LANG_ENUS, \ | |||||
USB_DESC_STRING(manuf), \ | |||||
USB_DESC_STRING(product), \ | |||||
USB_DESC_STRING_SERIALNO, \ | |||||
NULL \ | |||||
}, \ | |||||
.configs = { \ | |||||
USB_DESC_STRING_LANG_ENUS, \ | |||||
USB_DESC_STRING(manuf), \ | |||||
USB_DESC_STRING(product), \ | |||||
USB_DESC_STRING_SERIALNO, \ | |||||
NULL \ | |||||
}, \ | |||||
.configs = { \ | |||||
__REPEAT(1, USB__INCREMENT, USB__DEFINE_CONFIG, __VA_ARGS__) \ | __REPEAT(1, USB__INCREMENT, USB__DEFINE_CONFIG, __VA_ARGS__) \ | ||||
NULL \ | |||||
} \ | |||||
NULL \ | |||||
} \ | |||||
} | } | ||||
struct usb_desc_dev_t { | struct usb_desc_dev_t { | ||||
uint8_t bLength; | uint8_t bLength; | ||||
enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_DEV */ | enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_DEV */ | ||||
struct usb_bcd_t bcdUSB; /* = 0x0200 */ | |||||
struct usb_bcd_t bcdUSB; /* = 0x0200 */ | |||||
enum usb_dev_class bDeviceClass : 8; | enum usb_dev_class bDeviceClass : 8; | ||||
enum usb_dev_subclass bDeviceSubClass : 8; | enum usb_dev_subclass bDeviceSubClass : 8; | ||||
enum usb_dev_proto bDeviceProtocol : 8; | enum usb_dev_proto bDeviceProtocol : 8; | ||||
struct usb_desc_config_t { | struct usb_desc_config_t { | ||||
uint8_t bLength; | uint8_t bLength; | ||||
enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_CONFIG */ | enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_CONFIG */ | ||||
uint16_t wTotalLength; /* size of config, iface, ep */ | |||||
uint16_t wTotalLength; /* size of config, iface, ep */ | |||||
uint8_t bNumInterfaces; | uint8_t bNumInterfaces; | ||||
uint8_t bConfigurationValue; | uint8_t bConfigurationValue; | ||||
uint8_t iConfiguration; | uint8_t iConfiguration; | ||||
uint8_t self_powered : 1; | uint8_t self_powered : 1; | ||||
uint8_t one : 1; /* = 1 for historical reasons */ | uint8_t one : 1; /* = 1 for historical reasons */ | ||||
}; | }; | ||||
uint8_t bMaxPower; /* units of 2mA */ | |||||
uint8_t bMaxPower; /* units of 2mA */ | |||||
} __packed; | } __packed; | ||||
CTASSERT_SIZE_BYTE(struct usb_desc_config_t, 9); | CTASSERT_SIZE_BYTE(struct usb_desc_config_t, 9); | ||||
*/ | */ | ||||
struct USB_ADDINFO_t { | struct USB_ADDINFO_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t iehost : 1; | |||||
uint8_t _rsvd0 : 2; | |||||
uint8_t irqnum : 5; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t iehost : 1; | |||||
uint8_t _rsvd0 : 2; | |||||
uint8_t irqnum : 5; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_ADDINFO_t, 8); | CTASSERT_SIZE_BIT(struct USB_ADDINFO_t, 8); | ||||
struct USB_OTGSTAT_t { | struct USB_OTGSTAT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t avbus : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t b_sess : 1; | |||||
uint8_t sessvld : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t line_state : 1; | |||||
uint8_t onemsec : 1; | |||||
uint8_t idchg : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t avbus : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t b_sess : 1; | |||||
uint8_t sessvld : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t line_state : 1; | |||||
uint8_t onemsec : 1; | |||||
uint8_t idchg : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_OTGSTAT_t, 8); | CTASSERT_SIZE_BIT(struct USB_OTGSTAT_t, 8); | ||||
struct USB_OTGCTL_t { | struct USB_OTGCTL_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 2; | |||||
uint8_t otgen : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t dmlow : 1; | |||||
uint8_t dplow : 1; | |||||
uint8_t _rsvd2 : 1; | |||||
uint8_t dphigh : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 2; | |||||
uint8_t otgen : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t dmlow : 1; | |||||
uint8_t dplow : 1; | |||||
uint8_t _rsvd2 : 1; | |||||
uint8_t dphigh : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_OTGCTL_t, 8); | CTASSERT_SIZE_BIT(struct USB_OTGCTL_t, 8); | ||||
struct USB_ISTAT_t { | struct USB_ISTAT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t usbrst : 1; | |||||
uint8_t error : 1; | |||||
uint8_t softok : 1; | |||||
uint8_t tokdne : 1; | |||||
uint8_t sleep : 1; | |||||
uint8_t resume : 1; | |||||
uint8_t attach : 1; | |||||
uint8_t stall : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t usbrst : 1; | |||||
uint8_t error : 1; | |||||
uint8_t softok : 1; | |||||
uint8_t tokdne : 1; | |||||
uint8_t sleep : 1; | |||||
uint8_t resume : 1; | |||||
uint8_t attach : 1; | |||||
uint8_t stall : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_ISTAT_t, 8); | CTASSERT_SIZE_BIT(struct USB_ISTAT_t, 8); | ||||
struct USB_ERRSTAT_t { | struct USB_ERRSTAT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t piderr : 1; | |||||
uint8_t crc5eof : 1; | |||||
uint8_t crc16 : 1; | |||||
uint8_t dfn8 : 1; | |||||
uint8_t btoerr : 1; | |||||
uint8_t dmaerr : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t btserr : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t piderr : 1; | |||||
uint8_t crc5eof : 1; | |||||
uint8_t crc16 : 1; | |||||
uint8_t dfn8 : 1; | |||||
uint8_t btoerr : 1; | |||||
uint8_t dmaerr : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t btserr : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_ERRSTAT_t, 8); | CTASSERT_SIZE_BIT(struct USB_ERRSTAT_t, 8); | ||||
struct USB_STAT_t { | struct USB_STAT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 2; | |||||
enum usb_ep_pingpong pingpong : 1; | |||||
enum usb_ep_dir dir : 1; | |||||
uint8_t ep : 4; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 2; | |||||
enum usb_ep_pingpong pingpong : 1; | |||||
enum usb_ep_dir dir : 1; | |||||
uint8_t ep : 4; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_STAT_t, 8); | CTASSERT_SIZE_BIT(struct USB_STAT_t, 8); | ||||
struct USB_CTL_t { | struct USB_CTL_t { | ||||
union { | |||||
struct /* common */ { | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t oddrst : 1; | |||||
uint8_t resume : 1; | |||||
uint8_t _rsvd2 : 3; | |||||
uint8_t se0 : 1; | |||||
uint8_t jstate : 1; | |||||
}; | |||||
struct /* host */ { | |||||
uint8_t sofen : 1; | |||||
uint8_t _rsvd3 : 2; | |||||
uint8_t hostmodeen : 1; | |||||
uint8_t reset : 1; | |||||
uint8_t token_busy : 1; | |||||
uint8_t _rsvd4 : 2; | |||||
}; | |||||
struct /* device */ { | |||||
uint8_t usben : 1; | |||||
uint8_t _rsvd5 : 4; | |||||
uint8_t txd_suspend : 1; | |||||
uint8_t _rsvd6 : 2; | |||||
}; | |||||
uint8_t raw; | |||||
}; | |||||
union { | |||||
struct /* common */ { | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t oddrst : 1; | |||||
uint8_t resume : 1; | |||||
uint8_t _rsvd2 : 3; | |||||
uint8_t se0 : 1; | |||||
uint8_t jstate : 1; | |||||
}; | |||||
struct /* host */ { | |||||
uint8_t sofen : 1; | |||||
uint8_t _rsvd3 : 2; | |||||
uint8_t hostmodeen : 1; | |||||
uint8_t reset : 1; | |||||
uint8_t token_busy : 1; | |||||
uint8_t _rsvd4 : 2; | |||||
}; | |||||
struct /* device */ { | |||||
uint8_t usben : 1; | |||||
uint8_t _rsvd5 : 4; | |||||
uint8_t txd_suspend : 1; | |||||
uint8_t _rsvd6 : 2; | |||||
}; | |||||
uint8_t raw; | |||||
}; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_CTL_t, 8); | CTASSERT_SIZE_BIT(struct USB_CTL_t, 8); | ||||
struct USB_ADDR_t { | struct USB_ADDR_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t addr : 7; | |||||
uint8_t lsen : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t addr : 7; | |||||
uint8_t lsen : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_ADDR_t, 8); | CTASSERT_SIZE_BIT(struct USB_ADDR_t, 8); | ||||
struct USB_TOKEN_t { | struct USB_TOKEN_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t endpt : 4; | |||||
enum usb_tok_pid pid : 4; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t endpt : 4; | |||||
enum usb_tok_pid pid : 4; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_TOKEN_t, 8); | CTASSERT_SIZE_BIT(struct USB_TOKEN_t, 8); | ||||
struct USB_ENDPT_t { | struct USB_ENDPT_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t ephshk : 1; | |||||
uint8_t epstall : 1; | |||||
uint8_t eptxen : 1; | |||||
uint8_t eprxen : 1; | |||||
uint8_t epctldis : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t retrydis : 1; | |||||
uint8_t hostwohub : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t ephshk : 1; | |||||
uint8_t epstall : 1; | |||||
uint8_t eptxen : 1; | |||||
uint8_t eprxen : 1; | |||||
uint8_t epctldis : 1; | |||||
uint8_t _rsvd0 : 1; | |||||
uint8_t retrydis : 1; | |||||
uint8_t hostwohub : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_ENDPT_t, 8); | CTASSERT_SIZE_BIT(struct USB_ENDPT_t, 8); | ||||
struct USB_USBCTRL_t { | struct USB_USBCTRL_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 6; | |||||
uint8_t pde : 1; | |||||
uint8_t susp : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 6; | |||||
uint8_t pde : 1; | |||||
uint8_t susp : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_USBCTRL_t, 8); | CTASSERT_SIZE_BIT(struct USB_USBCTRL_t, 8); | ||||
struct USB_OBSERVE_t { | struct USB_OBSERVE_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 4; | |||||
uint8_t dmpd : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t dppd : 1; | |||||
uint8_t dppu : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 4; | |||||
uint8_t dmpd : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t dppd : 1; | |||||
uint8_t dppu : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_OBSERVE_t, 8); | CTASSERT_SIZE_BIT(struct USB_OBSERVE_t, 8); | ||||
struct USB_CONTROL_t { | struct USB_CONTROL_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 4; | |||||
uint8_t dppullupnonotg : 1; | |||||
uint8_t _rsvd1 : 3; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t _rsvd0 : 4; | |||||
uint8_t dppullupnonotg : 1; | |||||
uint8_t _rsvd1 : 3; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_CONTROL_t, 8); | CTASSERT_SIZE_BIT(struct USB_CONTROL_t, 8); | ||||
struct USB_USBTRC0_t { | struct USB_USBTRC0_t { | ||||
UNION_STRUCT_START(8); | |||||
uint8_t usb_resume_int : 1; | |||||
uint8_t sync_det : 1; | |||||
uint8_t _rsvd0 : 3; | |||||
uint8_t usbresmen : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t usbreset : 1; | |||||
UNION_STRUCT_END; | |||||
UNION_STRUCT_START(8); | |||||
uint8_t usb_resume_int : 1; | |||||
uint8_t sync_det : 1; | |||||
uint8_t _rsvd0 : 3; | |||||
uint8_t usbresmen : 1; | |||||
uint8_t _rsvd1 : 1; | |||||
uint8_t usbreset : 1; | |||||
UNION_STRUCT_END; | |||||
}; | }; | ||||
CTASSERT_SIZE_BIT(struct USB_USBTRC0_t, 8); | CTASSERT_SIZE_BIT(struct USB_USBTRC0_t, 8); | ||||
struct USB_t { | struct USB_t { | ||||
uint8_t perid; | |||||
uint8_t _pad0[3]; | |||||
uint8_t idcomp; | |||||
uint8_t _pad1[3]; | |||||
uint8_t rev; | |||||
uint8_t _pad2[3]; | |||||
struct USB_ADDINFO_t addinfo; | |||||
uint8_t _pad3[3]; | |||||
struct USB_OTGSTAT_t otgistat; | |||||
uint8_t _pad4[3]; | |||||
struct USB_OTGSTAT_t otgicr; | |||||
uint8_t _pad5[3]; | |||||
struct USB_OTGSTAT_t otgstat; | |||||
uint8_t _pad6[3]; | |||||
struct USB_OTGCTL_t otgctl; | |||||
uint8_t _pad7[3]; | |||||
uint8_t _pad8[0x80 - 0x20]; | |||||
struct USB_ISTAT_t istat; | |||||
uint8_t _pad9[3]; | |||||
struct USB_ISTAT_t inten; | |||||
uint8_t _pad10[3]; | |||||
struct USB_ERRSTAT_t errstat; | |||||
uint8_t _pad11[3]; | |||||
struct USB_ERRSTAT_t erren; | |||||
uint8_t _pad12[3]; | |||||
struct USB_STAT_t stat; | |||||
uint8_t _pad13[3]; | |||||
struct USB_CTL_t ctl; | |||||
uint8_t _pad14[3]; | |||||
struct USB_ADDR_t addr; | |||||
uint8_t _pad15[3]; | |||||
uint8_t bdtpage1; | |||||
uint8_t _pad16[3]; | |||||
uint8_t frmnuml; | |||||
uint8_t _pad17[3]; | |||||
struct { | |||||
uint8_t frmnumh : 3; | |||||
uint8_t _rsvd0 : 5; | |||||
}; | |||||
uint8_t _pad18[3]; | |||||
struct USB_TOKEN_t token; | |||||
uint8_t _pad19[3]; | |||||
uint8_t softhld; | |||||
uint8_t _pad20[3]; | |||||
uint8_t bdtpage2; | |||||
uint8_t _pad21[3]; | |||||
uint8_t bdtpage3; | |||||
uint8_t _pad22[3]; | |||||
uint8_t _pad23[0xc0 - 0xb8]; | |||||
struct { | |||||
struct USB_ENDPT_t; | |||||
uint8_t _pad24[3]; | |||||
} endpt[16]; | |||||
struct USB_USBCTRL_t usbctrl; | |||||
uint8_t _pad25[3]; | |||||
struct USB_OBSERVE_t observe; | |||||
uint8_t _pad26[3]; | |||||
struct USB_CONTROL_t control; | |||||
uint8_t _pad27[3]; | |||||
struct USB_USBTRC0_t usbtrc0; | |||||
uint8_t _pad28[3]; | |||||
uint8_t _pad29[4]; | |||||
uint8_t usbfrmadjust; | |||||
uint8_t _pad30[3]; | |||||
uint8_t perid; | |||||
uint8_t _pad0[3]; | |||||
uint8_t idcomp; | |||||
uint8_t _pad1[3]; | |||||
uint8_t rev; | |||||
uint8_t _pad2[3]; | |||||
struct USB_ADDINFO_t addinfo; | |||||
uint8_t _pad3[3]; | |||||
struct USB_OTGSTAT_t otgistat; | |||||
uint8_t _pad4[3]; | |||||
struct USB_OTGSTAT_t otgicr; | |||||
uint8_t _pad5[3]; | |||||
struct USB_OTGSTAT_t otgstat; | |||||
uint8_t _pad6[3]; | |||||
struct USB_OTGCTL_t otgctl; | |||||
uint8_t _pad7[3]; | |||||
uint8_t _pad8[0x80 - 0x20]; | |||||
struct USB_ISTAT_t istat; | |||||
uint8_t _pad9[3]; | |||||
struct USB_ISTAT_t inten; | |||||
uint8_t _pad10[3]; | |||||
struct USB_ERRSTAT_t errstat; | |||||
uint8_t _pad11[3]; | |||||
struct USB_ERRSTAT_t erren; | |||||
uint8_t _pad12[3]; | |||||
struct USB_STAT_t stat; | |||||
uint8_t _pad13[3]; | |||||
struct USB_CTL_t ctl; | |||||
uint8_t _pad14[3]; | |||||
struct USB_ADDR_t addr; | |||||
uint8_t _pad15[3]; | |||||
uint8_t bdtpage1; | |||||
uint8_t _pad16[3]; | |||||
uint8_t frmnuml; | |||||
uint8_t _pad17[3]; | |||||
struct { | |||||
uint8_t frmnumh : 3; | |||||
uint8_t _rsvd0 : 5; | |||||
}; | |||||
uint8_t _pad18[3]; | |||||
struct USB_TOKEN_t token; | |||||
uint8_t _pad19[3]; | |||||
uint8_t softhld; | |||||
uint8_t _pad20[3]; | |||||
uint8_t bdtpage2; | |||||
uint8_t _pad21[3]; | |||||
uint8_t bdtpage3; | |||||
uint8_t _pad22[3]; | |||||
uint8_t _pad23[0xc0 - 0xb8]; | |||||
struct { | |||||
struct USB_ENDPT_t; | |||||
uint8_t _pad24[3]; | |||||
} endpt[16]; | |||||
struct USB_USBCTRL_t usbctrl; | |||||
uint8_t _pad25[3]; | |||||
struct USB_OBSERVE_t observe; | |||||
uint8_t _pad26[3]; | |||||
struct USB_CONTROL_t control; | |||||
uint8_t _pad27[3]; | |||||
struct USB_USBTRC0_t usbtrc0; | |||||
uint8_t _pad28[3]; | |||||
uint8_t _pad29[4]; | |||||
uint8_t usbfrmadjust; | |||||
uint8_t _pad30[3]; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct USB_t, 0x118); | CTASSERT_SIZE_BYTE(struct USB_t, 0x118); | ||||
struct USB_BD_t { | struct USB_BD_t { | ||||
struct USB_BD_BITS_t { | |||||
union { | |||||
struct { | |||||
uint32_t _rsvd0 : 2; | |||||
uint32_t stall : 1; | |||||
uint32_t dts : 1; | |||||
uint32_t ninc : 1; | |||||
uint32_t keep : 1; | |||||
enum usb_data01 data01 : 1; | |||||
uint32_t own : 1; | |||||
uint32_t _rsvd1 : 8; | |||||
uint32_t bc : 10; | |||||
uint32_t _rsvd2 : 6; | |||||
}; | |||||
struct /* processor */ { | |||||
uint32_t _rsvd5 : 2; | |||||
enum usb_tok_pid tok_pid : 4; | |||||
uint32_t _rsvd6 : 26; | |||||
}; | |||||
uint32_t raw; | |||||
}; | |||||
}; | |||||
void *addr; | |||||
struct USB_BD_BITS_t { | |||||
union { | |||||
struct { | |||||
uint32_t _rsvd0 : 2; | |||||
uint32_t stall : 1; | |||||
uint32_t dts : 1; | |||||
uint32_t ninc : 1; | |||||
uint32_t keep : 1; | |||||
enum usb_data01 data01 : 1; | |||||
uint32_t own : 1; | |||||
uint32_t _rsvd1 : 8; | |||||
uint32_t bc : 10; | |||||
uint32_t _rsvd2 : 6; | |||||
}; | |||||
struct /* processor */ { | |||||
uint32_t _rsvd5 : 2; | |||||
enum usb_tok_pid tok_pid : 4; | |||||
uint32_t _rsvd6 : 26; | |||||
}; | |||||
uint32_t raw; | |||||
}; | |||||
}; | |||||
void *addr; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct USB_BD_t, 8); | CTASSERT_SIZE_BYTE(struct USB_BD_t, 8); | ||||
#| You _MUST_ clean the build directory if you change this value | #| You _MUST_ clean the build directory if you change this value | ||||
#| | #| | ||||
set( CHIP | set( CHIP | ||||
# "at90usb162" # Teensy 1.0 (avr) | |||||
# "atmega32u4" # Teensy 2.0 (avr) | |||||
# "at90usb646" # Teensy++ 1.0 (avr) | |||||
# "at90usb1286" # Teensy++ 2.0 (avr) | |||||
# "mk20dx128" # Teensy 3.0 (arm) | |||||
# "at90usb162" # Teensy 1.0 (avr) | |||||
# "atmega32u4" # Teensy 2.0 (avr) | |||||
# "at90usb646" # Teensy++ 1.0 (avr) | |||||
# "at90usb1286" # Teensy++ 2.0 (avr) | |||||
# "mk20dx128" # Teensy 3.0 (arm) | |||||
"mk20dx128vlf5" # McHCK mk20dx128vlf5 | "mk20dx128vlf5" # McHCK mk20dx128vlf5 | ||||
# "mk20dx256" # Teensy 3.1 (arm) | |||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | |||||
# "mk20dx256" # Teensy 3.1 (arm) | |||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | |||||
CACHE STRING "Microcontroller Chip" ) | CACHE STRING "Microcontroller Chip" ) | ||||
#| Stick with gcc unless you know what you're doing | #| Stick with gcc unless you know what you're doing | ||||
#| Currently only arm is supported with clang | #| Currently only arm is supported with clang | ||||
set( COMPILER | set( COMPILER | ||||
"gcc" # arm-none-eabi-gcc / avr-gcc - Default | |||||
# "clang" # arm-none-eabi | |||||
"gcc" # arm-none-eabi-gcc / avr-gcc - Default | |||||
# "clang" # arm-none-eabi | |||||
CACHE STRING "Compiler Type" ) | CACHE STRING "Compiler Type" ) | ||||
// Special Msg Constructs (Uses VT100 tags) | // Special Msg Constructs (Uses VT100 tags) | ||||
#define dPrintMsg(colour_code_str,msg,...) \ | #define dPrintMsg(colour_code_str,msg,...) \ | ||||
printstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") | |||||
printstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") | |||||
#define printMsgNL(colour_code_str,msg,str) \ | #define printMsgNL(colour_code_str,msg,str) \ | ||||
print("\033[" colour_code_str "m" msg "\033[0m - " str NL) | |||||
print("\033[" colour_code_str "m" msg "\033[0m - " str NL) | |||||
#define printMsg(colour_code_str,msg,str) \ | #define printMsg(colour_code_str,msg,str) \ | ||||
print("\033[" colour_code_str "m" msg "\033[0m - " str) | |||||
print("\033[" colour_code_str "m" msg "\033[0m - " str) | |||||
// Info Messages | // Info Messages | ||||
#define info_dPrint(...) dPrintMsg ("1;32", "INFO", __VA_ARGS__) // Info Msg | #define info_dPrint(...) dPrintMsg ("1;32", "INFO", __VA_ARGS__) // Info Msg |
// Windows, even though the driver is supplied by Microsoft, an | // Windows, even though the driver is supplied by Microsoft, an | ||||
// INF file is needed to load the driver. These numbers need to | // INF file is needed to load the driver. These numbers need to | ||||
// match the INF file. | // match the INF file. | ||||
#define VENDOR_ID @VENDOR_ID@ | |||||
#define PRODUCT_ID @PRODUCT_ID@ | |||||
#define VENDOR_ID @VENDOR_ID@ | |||||
#define PRODUCT_ID @PRODUCT_ID@ | |||||
#endif | #endif | ||||
uint32_t n = usec << 3; | uint32_t n = usec << 3; | ||||
#endif | #endif | ||||
asm volatile( | asm volatile( | ||||
"L_%=_delayMicroseconds:" "\n\t" | |||||
"subs %0, #1" "\n\t" | |||||
"bne L_%=_delayMicroseconds" "\n" | |||||
"L_%=_delayMicroseconds:" "\n\t" | |||||
"subs %0, #1" "\n\t" | |||||
"bne L_%=_delayMicroseconds" "\n" | |||||
: "+r" (n) : | : "+r" (n) : | ||||
); | ); | ||||
} | } |
__attribute__((noreturn)) | __attribute__((noreturn)) | ||||
static inline void jump_to_app( uintptr_t addr ) | static inline void jump_to_app( uintptr_t addr ) | ||||
{ | { | ||||
// addr is in r0 | |||||
__asm__("ldr sp, [%[addr], #0]\n" | |||||
"ldr pc, [%[addr], #4]" | |||||
:: [addr] "r" (addr)); | |||||
// NOTREACHED | |||||
__builtin_unreachable(); | |||||
// addr is in r0 | |||||
__asm__("ldr sp, [%[addr], #0]\n" | |||||
"ldr pc, [%[addr], #4]" | |||||
:: [addr] "r" (addr)); | |||||
// NOTREACHED | |||||
__builtin_unreachable(); | |||||
} | } | ||||
#endif | #endif | ||||
NVIC_SET_PRIORITY( i, 128 ); | NVIC_SET_PRIORITY( i, 128 ); | ||||
} | } | ||||
// FLL at 48MHz | |||||
// FLL at 48MHz | |||||
MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 ); | MCG_C4 = MCG_C4_DMX32 | MCG_C4_DRST_DRS( 1 ); | ||||
// USB Clock and FLL select | // USB Clock and FLL select | ||||
// Teensy 3.0 and 3.1 and Kiibohd-dfu (mk20dx256vlh7) | // Teensy 3.0 and 3.1 and Kiibohd-dfu (mk20dx256vlh7) | ||||
#else | #else | ||||
SCB_VTOR = 0; // use vector table in flash | |||||
SCB_VTOR = 0; // use vector table in flash | |||||
// default all interrupts to medium priority level | // default all interrupts to medium priority level | ||||
for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) | for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) |
num = read_intel_hex(filename); | num = read_intel_hex(filename); | ||||
if (num < 0) die("error reading intel hex file \"%s\"", filename); | if (num < 0) die("error reading intel hex file \"%s\"", filename); | ||||
printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n", | printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n", | ||||
filename, num, (double)num / (double)code_size * 100.0); | |||||
filename, num, (double)num / (double)code_size * 100.0); | |||||
} | } | ||||
// program the data | // program the data | ||||
parse_hex_line(char *line) | parse_hex_line(char *line) | ||||
{ | { | ||||
int addr, code, num; | int addr, code, num; | ||||
int sum, len, cksum, i; | |||||
char *ptr; | |||||
num = 0; | |||||
if (line[0] != ':') return 0; | |||||
if (strlen(line) < 11) return 0; | |||||
ptr = line+1; | |||||
if (!sscanf(ptr, "%02x", &len)) return 0; | |||||
ptr += 2; | |||||
if ((int)strlen(line) < (11 + (len * 2)) ) return 0; | |||||
if (!sscanf(ptr, "%04x", &addr)) return 0; | |||||
ptr += 4; | |||||
/* printf("Line: length=%d Addr=%d\n", len, addr); */ | |||||
if (!sscanf(ptr, "%02x", &code)) return 0; | |||||
int sum, len, cksum, i; | |||||
char *ptr; | |||||
num = 0; | |||||
if (line[0] != ':') return 0; | |||||
if (strlen(line) < 11) return 0; | |||||
ptr = line+1; | |||||
if (!sscanf(ptr, "%02x", &len)) return 0; | |||||
ptr += 2; | |||||
if ((int)strlen(line) < (11 + (len * 2)) ) return 0; | |||||
if (!sscanf(ptr, "%04x", &addr)) return 0; | |||||
ptr += 4; | |||||
/* printf("Line: length=%d Addr=%d\n", len, addr); */ | |||||
if (!sscanf(ptr, "%02x", &code)) return 0; | |||||
if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0; | if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0; | ||||
ptr += 2; | |||||
sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255); | |||||
ptr += 2; | |||||
sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255); | |||||
if (code != 0) { | if (code != 0) { | ||||
if (code == 1) { | if (code == 1) { | ||||
end_record_seen = 1; | end_record_seen = 1; | ||||
if (!sscanf(ptr, "%04x", &i)) return 1; | if (!sscanf(ptr, "%04x", &i)) return 1; | ||||
ptr += 4; | ptr += 4; | ||||
sum += ((i >> 8) & 255) + (i & 255); | sum += ((i >> 8) & 255) + (i & 255); | ||||
if (!sscanf(ptr, "%02x", &cksum)) return 1; | |||||
if (!sscanf(ptr, "%02x", &cksum)) return 1; | |||||
if (((sum & 255) + (cksum & 255)) & 255) return 1; | if (((sum & 255) + (cksum & 255)) & 255) return 1; | ||||
extended_addr = i << 4; | extended_addr = i << 4; | ||||
//printf("ext addr = %05X\n", extended_addr); | //printf("ext addr = %05X\n", extended_addr); | ||||
if (!sscanf(ptr, "%04x", &i)) return 1; | if (!sscanf(ptr, "%04x", &i)) return 1; | ||||
ptr += 4; | ptr += 4; | ||||
sum += ((i >> 8) & 255) + (i & 255); | sum += ((i >> 8) & 255) + (i & 255); | ||||
if (!sscanf(ptr, "%02x", &cksum)) return 1; | |||||
if (!sscanf(ptr, "%02x", &cksum)) return 1; | |||||
if (((sum & 255) + (cksum & 255)) & 255) return 1; | if (((sum & 255) + (cksum & 255)) & 255) return 1; | ||||
extended_addr = i << 16; | extended_addr = i << 16; | ||||
//printf("ext addr = %08X\n", extended_addr); | //printf("ext addr = %08X\n", extended_addr); | ||||
} | } | ||||
return 1; // non-data line | |||||
return 1; // non-data line | |||||
} | } | ||||
byte_count += len; | byte_count += len; | ||||
while (num != len) { | |||||
if (sscanf(ptr, "%02x", &i) != 1) return 0; | |||||
while (num != len) { | |||||
if (sscanf(ptr, "%02x", &i) != 1) return 0; | |||||
i &= 255; | i &= 255; | ||||
firmware_image[addr + extended_addr + num] = i; | firmware_image[addr + extended_addr + num] = i; | ||||
firmware_mask[addr + extended_addr + num] = 1; | firmware_mask[addr + extended_addr + num] = 1; | ||||
ptr += 2; | |||||
sum += i; | |||||
(num)++; | |||||
if (num >= 256) return 0; | |||||
} | |||||
if (!sscanf(ptr, "%02x", &cksum)) return 0; | |||||
if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */ | |||||
return 1; | |||||
ptr += 2; | |||||
sum += i; | |||||
(num)++; | |||||
if (num >= 256) return 0; | |||||
} | |||||
if (!sscanf(ptr, "%02x", &cksum)) return 0; | |||||
if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */ | |||||
return 1; | |||||
} | } | ||||
int ihex_bytes_within_range(int begin, int end) | int ihex_bytes_within_range(int begin, int end) |
// List of Modifiers | // List of Modifiers | ||||
#define KEY_CTRL 0x01 | #define KEY_CTRL 0x01 | ||||
#define KEY_SHIFT 0x02 | #define KEY_SHIFT 0x02 | ||||
#define KEY_ALT 0x04 | |||||
#define KEY_GUI 0x08 | |||||
#define KEY_ALT 0x04 | |||||
#define KEY_GUI 0x08 | |||||
#define KEY_LEFT_CTRL 0x01 | #define KEY_LEFT_CTRL 0x01 | ||||
#define KEY_LEFT_SHIFT 0x02 | #define KEY_LEFT_SHIFT 0x02 | ||||
#define KEY_LEFT_ALT 0x04 | #define KEY_LEFT_ALT 0x04 |
// USB Device Descriptor. The USB host reads this first, to learn | // USB Device Descriptor. The USB host reads this first, to learn | ||||
// what type of device is connected. | // what type of device is connected. | ||||
static uint8_t device_descriptor[] = { | static uint8_t device_descriptor[] = { | ||||
18, // bLength | |||||
1, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
DEVICE_CLASS, // bDeviceClass | |||||
DEVICE_SUBCLASS, // bDeviceSubClass | |||||
DEVICE_PROTOCOL, // bDeviceProtocol | |||||
EP0_SIZE, // bMaxPacketSize0 | |||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | |||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | |||||
0x00, 0x01, // bcdDevice | |||||
1, // iManufacturer | |||||
2, // iProduct | |||||
3, // iSerialNumber | |||||
1 // bNumConfigurations | |||||
18, // bLength | |||||
1, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
DEVICE_CLASS, // bDeviceClass | |||||
DEVICE_SUBCLASS, // bDeviceSubClass | |||||
DEVICE_PROTOCOL, // bDeviceProtocol | |||||
EP0_SIZE, // bMaxPacketSize0 | |||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | |||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | |||||
0x00, 0x01, // bcdDevice | |||||
1, // iManufacturer | |||||
2, // iProduct | |||||
3, // iSerialNumber | |||||
1 // bNumConfigurations | |||||
}; | }; | ||||
// USB Device Qualifier Descriptor | // USB Device Qualifier Descriptor | ||||
static uint8_t device_qualifier_descriptor[] = { | static uint8_t device_qualifier_descriptor[] = { | ||||
0 // Indicate only single speed | 0 // Indicate only single speed | ||||
/* Device qualifier example (used for specifying multiple USB speeds) | /* Device qualifier example (used for specifying multiple USB speeds) | ||||
10, // bLength | |||||
6, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
DEVICE_CLASS, // bDeviceClass | |||||
DEVICE_SUBCLASS, // bDeviceSubClass | |||||
DEVICE_PROTOCOL, // bDeviceProtocol | |||||
EP0_SIZE, // bMaxPacketSize0 | |||||
10, // bLength | |||||
6, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
DEVICE_CLASS, // bDeviceClass | |||||
DEVICE_SUBCLASS, // bDeviceSubClass | |||||
DEVICE_PROTOCOL, // bDeviceProtocol | |||||
EP0_SIZE, // bMaxPacketSize0 | |||||
0, // bNumOtherSpeedConfigurations | 0, // bNumOtherSpeedConfigurations | ||||
0 // bReserved | 0 // bReserved | ||||
*/ | */ | ||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||||
static uint8_t keyboard_report_desc[] = { | static uint8_t keyboard_report_desc[] = { | ||||
// Keyboard Collection | // Keyboard Collection | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
// Modifier Byte | // Modifier Byte | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
// Reserved Byte | // Reserved Byte | ||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x03, // Output (Constant), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x03, // Output (Constant), | |||||
// LED Report | // LED Report | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
// LED Report Padding | // LED Report Padding | ||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
// Normal Keys | // Normal Keys | ||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x06, // Report Count (6), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x7F, // Logical Maximum(104), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, 0x7F, // Usage Maximum (104), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Keyboard | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x06, // Report Count (6), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x7F, // Logical Maximum(104), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, 0x7F, // Usage Maximum (104), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Keyboard | |||||
}; | }; | ||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||||
static uint8_t nkro_keyboard_report_desc[] = { | static uint8_t nkro_keyboard_report_desc[] = { | ||||
// Keyboard Collection | // Keyboard Collection | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
// LED Report | // LED Report | ||||
0x85, 0x01, // Report ID (1), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x85, 0x01, // Report ID (1), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
// LED Report Padding | // LED Report Padding | ||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
// Normal Keys - Using an NKRO Bitmap | // Normal Keys - Using an NKRO Bitmap | ||||
// | // | ||||
// 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) | // 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) | ||||
// Modifier Byte | // Modifier Byte | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
// 4-49 (6 bytes/46 bits) - MainKeys | // 4-49 (6 bytes/46 bits) - MainKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x04, // Usage Minimum (4), | |||||
0x29, 0x31, // Usage Maximum (49), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x04, // Usage Minimum (4), | |||||
0x29, 0x31, // Usage Maximum (49), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (2 bits) | // Padding (2 bits) | ||||
0x75, 0x02, // Report Size (2), | 0x75, 0x02, // Report Size (2), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
// 51-155 (14 bytes/105 bits) - SecondaryKeys | // 51-155 (14 bytes/105 bits) - SecondaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x69, // Report Count (105), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x33, // Usage Minimum (51), | |||||
0x29, 0x9B, // Usage Maximum (155), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x69, // Report Count (105), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x33, // Usage Minimum (51), | |||||
0x29, 0x9B, // Usage Maximum (155), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (7 bits) | // Padding (7 bits) | ||||
0x75, 0x07, // Report Size (7), | 0x75, 0x07, // Report Size (7), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
// 157-164 (1 byte/8 bits) - TertiaryKeys | // 157-164 (1 byte/8 bits) - TertiaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x9D, // Usage Minimum (157), | |||||
0x29, 0xA4, // Usage Maximum (164), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x9D, // Usage Minimum (157), | |||||
0x29, 0xA4, // Usage Maximum (164), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// 176-221 (6 bytes/46 bits) - QuartiaryKeys | // 176-221 (6 bytes/46 bits) - QuartiaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xB0, // Usage Minimum (176), | |||||
0x29, 0xDD, // Usage Maximum (221), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xB0, // Usage Minimum (176), | |||||
0x29, 0xDD, // Usage Maximum (221), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (2 bits) | // Padding (2 bits) | ||||
0x75, 0x02, // Report Size (2), | 0x75, 0x02, // Report Size (2), | ||||
0x95, 0x01, // Report Count (1), | 0x95, 0x01, // Report Count (1), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
0xc0, // End Collection - Keyboard | |||||
0xc0, // End Collection - Keyboard | |||||
// System Control Collection | // System Control Collection | ||||
// | // | ||||
// NOTES: | // NOTES: | ||||
// Not bothering with NKRO for this table. If there's need, I can implement it. -HaaTa | // Not bothering with NKRO for this table. If there's need, I can implement it. -HaaTa | ||||
// Using a 1KRO scheme | // Using a 1KRO scheme | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x80, // Usage (System Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x02, // Report ID (2), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x81, 0x00, // Logical Minimum (129), | |||||
0x26, 0xB7, 0x00, // Logical Maximum (183), | |||||
0x19, 0x81, // Usage Minimum (129), | |||||
0x29, 0xB7, // Usage Maximum (183), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - System Control | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x80, // Usage (System Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x02, // Report ID (2), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x81, 0x00, // Logical Minimum (129), | |||||
0x26, 0xB7, 0x00, // Logical Maximum (183), | |||||
0x19, 0x81, // Usage Minimum (129), | |||||
0x29, 0xB7, // Usage Maximum (183), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - System Control | |||||
// Consumer Control Collection - Media Keys | // Consumer Control Collection - Media Keys | ||||
// | // | ||||
// NOTES: | // NOTES: | ||||
// Not bothering with NKRO for this table. If there's a need, I can implement it. -HaaTa | // Not bothering with NKRO for this table. If there's a need, I can implement it. -HaaTa | ||||
// Using a 1KRO scheme | // Using a 1KRO scheme | ||||
0x05, 0x0c, // Usage Page (Consumer), | |||||
0x09, 0x01, // Usage (Consumer Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x03, // Report ID (3), | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x20, 0x00, // Logical Minimum (32), | |||||
0x26, 0x9C, 0x02, // Logical Maximum (668), | |||||
0x05, 0x0C, // Usage Page (Consumer), | |||||
0x19, 0x20, // Usage Minimum (32), | |||||
0x2A, 0x9C, 0x02, // Usage Maximum (668), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Consumer Control | |||||
0x05, 0x0c, // Usage Page (Consumer), | |||||
0x09, 0x01, // Usage (Consumer Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x03, // Report ID (3), | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x20, 0x00, // Logical Minimum (32), | |||||
0x26, 0x9C, 0x02, // Logical Maximum (668), | |||||
0x05, 0x0C, // Usage Page (Consumer), | |||||
0x19, 0x20, // Usage Minimum (32), | |||||
0x2A, 0x9C, 0x02, // Usage Maximum (668), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Consumer Control | |||||
}; | }; | ||||
/* MOUSE | /* MOUSE | ||||
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension | // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension | ||||
static uint8_t mouse_report_desc[] = { | static uint8_t mouse_report_desc[] = { | ||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x02, // Usage (Mouse) | |||||
0xA1, 0x01, // Collection (Application) | |||||
0x05, 0x09, // Usage Page (Button) | |||||
0x19, 0x01, // Usage Minimum (Button #1) | |||||
0x29, 0x03, // Usage Maximum (Button #3) | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x25, 0x01, // Logical Maximum (1) | |||||
0x95, 0x03, // Report Count (3) | |||||
0x75, 0x01, // Report Size (1) | |||||
0x81, 0x02, // Input (Data, Variable, Absolute) | |||||
0x95, 0x01, // Report Count (1) | |||||
0x75, 0x05, // Report Size (5) | |||||
0x81, 0x03, // Input (Constant) | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x30, // Usage (X) | |||||
0x09, 0x31, // Usage (Y) | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x26, 0xFF, 0x7F, // Logical Maximum (32767) | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x02, // Report Count (2), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute) | |||||
0x09, 0x38, // Usage (Wheel) | |||||
0x15, 0x81, // Logical Minimum (-127) | |||||
0x25, 0x7F, // Logical Maximum (127) | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x06, // Input (Data, Variable, Relative) | |||||
0xC0 // End Collection | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x02, // Usage (Mouse) | |||||
0xA1, 0x01, // Collection (Application) | |||||
0x05, 0x09, // Usage Page (Button) | |||||
0x19, 0x01, // Usage Minimum (Button #1) | |||||
0x29, 0x03, // Usage Maximum (Button #3) | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x25, 0x01, // Logical Maximum (1) | |||||
0x95, 0x03, // Report Count (3) | |||||
0x75, 0x01, // Report Size (1) | |||||
0x81, 0x02, // Input (Data, Variable, Absolute) | |||||
0x95, 0x01, // Report Count (1) | |||||
0x75, 0x05, // Report Size (5) | |||||
0x81, 0x03, // Input (Constant) | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x30, // Usage (X) | |||||
0x09, 0x31, // Usage (Y) | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x26, 0xFF, 0x7F, // Logical Maximum (32767) | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x02, // Report Count (2), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute) | |||||
0x09, 0x38, // Usage (Wheel) | |||||
0x15, 0x81, // Logical Minimum (-127) | |||||
0x25, 0x7F, // Logical Maximum (127) | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x06, // Input (Data, Variable, Relative) | |||||
0xC0 // End Collection | |||||
}; | }; | ||||
*/ | */ | ||||
static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { | static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { | ||||
// --- Configuration --- | // --- Configuration --- | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | |||||
9, // bLength; | |||||
2, // bDescriptorType; | |||||
LSB(CONFIG_DESC_SIZE), // wTotalLength | |||||
MSB(CONFIG_DESC_SIZE), | |||||
NUM_INTERFACE, // bNumInterfaces | |||||
1, // bConfigurationValue | |||||
0, // iConfiguration | |||||
0xA0, // bmAttributes | |||||
250, // bMaxPower | |||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | |||||
9, // bLength; | |||||
2, // bDescriptorType; | |||||
LSB(CONFIG_DESC_SIZE), // wTotalLength | |||||
MSB(CONFIG_DESC_SIZE), | |||||
NUM_INTERFACE, // bNumInterfaces | |||||
1, // bConfigurationValue | |||||
0, // iConfiguration | |||||
0xA0, // bmAttributes | |||||
250, // bMaxPower | |||||
// --- Keyboard HID --- Boot Mode Keyboard Interface | // --- Keyboard HID --- Boot Mode Keyboard Interface | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(keyboard_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(keyboard_report_desc)), | |||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(keyboard_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(keyboard_report_desc)), | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
KEYBOARD_INTERVAL, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
KEYBOARD_INTERVAL, // bInterval | |||||
// --- NKRO Keyboard HID --- OS Mode Keyboard Interface | // --- NKRO Keyboard HID --- OS Mode Keyboard Interface | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
NKRO_KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
NKRO_KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(nkro_keyboard_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(nkro_keyboard_report_desc)), | |||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(nkro_keyboard_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(nkro_keyboard_report_desc)), | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
NKRO_KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
NKRO_KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
NKRO_KEYBOARD_INTERVAL, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
NKRO_KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
NKRO_KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
NKRO_KEYBOARD_INTERVAL, // bInterval | |||||
// --- Serial CDC --- CDC IAD Descriptor | // --- Serial CDC --- CDC IAD Descriptor | ||||
// - 8 bytes - | // - 8 bytes - | ||||
// interface association descriptor, USB ECN, Table 9-Z | |||||
8, // bLength | |||||
11, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bFirstInterface | |||||
2, // bInterfaceCount | |||||
0x02, // bFunctionClass | |||||
0x02, // bFunctionSubClass | |||||
0x01, // bFunctionProtocol | |||||
0, // iFunction | |||||
// interface association descriptor, USB ECN, Table 9-Z | |||||
8, // bLength | |||||
11, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bFirstInterface | |||||
2, // bInterfaceCount | |||||
0x02, // bFunctionClass | |||||
0x02, // bFunctionSubClass | |||||
0x01, // bFunctionProtocol | |||||
0, // iFunction | |||||
// --- Serial CDC --- CDC Data Interface | // --- Serial CDC --- CDC Data Interface | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x02, // bInterfaceClass | |||||
0x02, // bInterfaceSubClass | |||||
0x01, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x02, // bInterfaceClass | |||||
0x02, // bInterfaceSubClass | |||||
0x01, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x00, // bDescriptorSubtype | |||||
0x10, 0x01, // bcdCDC | |||||
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x00, // bDescriptorSubtype | |||||
0x10, 0x01, // bcdCDC | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x01, // bDescriptorSubtype | |||||
0x01, // bmCapabilities | |||||
CDC_DATA_INTERFACE, // bDataInterface | |||||
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x01, // bDescriptorSubtype | |||||
0x01, // bmCapabilities | |||||
CDC_DATA_INTERFACE, // bDataInterface | |||||
// - 4 bytes - | // - 4 bytes - | ||||
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | |||||
4, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x02, // bDescriptorSubtype | |||||
0x06, // bmCapabilities | |||||
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | |||||
4, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x02, // bDescriptorSubtype | |||||
0x06, // bmCapabilities | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x06, // bDescriptorSubtype | |||||
CDC_STATUS_INTERFACE, // bMasterInterface | |||||
CDC_DATA_INTERFACE, // bSlaveInterface0 | |||||
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x06, // bDescriptorSubtype | |||||
CDC_STATUS_INTERFACE, // bMasterInterface | |||||
CDC_DATA_INTERFACE, // bSlaveInterface0 | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
CDC_ACM_SIZE, 0, // wMaxPacketSize | |||||
64, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
CDC_ACM_SIZE, 0, // wMaxPacketSize | |||||
64, // bInterval | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_DATA_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
2, // bNumEndpoints | |||||
0x0A, // bInterfaceClass | |||||
0x00, // bInterfaceSubClass | |||||
0x00, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_DATA_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
2, // bNumEndpoints | |||||
0x0A, // bInterfaceClass | |||||
0x00, // bInterfaceSubClass | |||||
0x00, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_RX_ENDPOINT, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_RX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_RX_ENDPOINT, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_RX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_TX_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_TX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_TX_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_TX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
/* | /* | ||||
// Mouse Interface | // Mouse Interface | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
MOUSE_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x01 = Boot) | |||||
0x00, // bInterfaceProtocol (0x02 = Mouse) | |||||
0, // iInterface | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
MOUSE_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x01 = Boot) | |||||
0x00, // bInterfaceProtocol (0x02 = Mouse) | |||||
0, // iInterface | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(mouse_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(mouse_report_desc)), | |||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(mouse_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(mouse_report_desc)), | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
MOUSE_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
MOUSE_SIZE, 0, // wMaxPacketSize | |||||
MOUSE_INTERVAL, // bInterval | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
MOUSE_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
MOUSE_SIZE, 0, // wMaxPacketSize | |||||
MOUSE_INTERVAL, // bInterval | |||||
#endif // MOUSE_INTERFACE | #endif // MOUSE_INTERFACE | ||||
*/ | */ | ||||
}; | }; | ||||
// actual string data | // actual string data | ||||
struct usb_string_descriptor_struct { | struct usb_string_descriptor_struct { | ||||
uint8_t bLength; | |||||
uint8_t bDescriptorType; | |||||
uint16_t wString[]; | |||||
uint8_t bLength; | |||||
uint8_t bDescriptorType; | |||||
uint16_t wString[]; | |||||
}; | }; | ||||
extern struct usb_string_descriptor_struct usb_string_manufacturer_name | extern struct usb_string_descriptor_struct usb_string_manufacturer_name | ||||
__attribute__ ((weak, alias("usb_string_manufacturer_name_default"))); | |||||
__attribute__ ((weak, alias("usb_string_manufacturer_name_default"))); | |||||
extern struct usb_string_descriptor_struct usb_string_product_name | extern struct usb_string_descriptor_struct usb_string_product_name | ||||
__attribute__ ((weak, alias("usb_string_product_name_default"))); | |||||
__attribute__ ((weak, alias("usb_string_product_name_default"))); | |||||
extern struct usb_string_descriptor_struct usb_string_serial_number | extern struct usb_string_descriptor_struct usb_string_serial_number | ||||
__attribute__ ((weak, alias("usb_string_serial_number_default"))); | |||||
__attribute__ ((weak, alias("usb_string_serial_number_default"))); | |||||
struct usb_string_descriptor_struct string0 = { | struct usb_string_descriptor_struct string0 = { | ||||
4, | |||||
3, | |||||
{0x0409} | |||||
4, | |||||
3, | |||||
{0x0409} | |||||
}; | }; | ||||
struct usb_string_descriptor_struct usb_string_manufacturer_name_default = { | struct usb_string_descriptor_struct usb_string_manufacturer_name_default = { | ||||
sizeof(STR_MANUFACTURER), | |||||
3, | |||||
{STR_MANUFACTURER} | |||||
sizeof(STR_MANUFACTURER), | |||||
3, | |||||
{STR_MANUFACTURER} | |||||
}; | }; | ||||
struct usb_string_descriptor_struct usb_string_product_name_default = { | struct usb_string_descriptor_struct usb_string_product_name_default = { | ||||
sizeof(STR_PRODUCT), | sizeof(STR_PRODUCT), | ||||
3, | |||||
{STR_PRODUCT} | |||||
3, | |||||
{STR_PRODUCT} | |||||
}; | }; | ||||
struct usb_string_descriptor_struct usb_string_serial_number_default = { | struct usb_string_descriptor_struct usb_string_serial_number_default = { | ||||
sizeof(STR_SERIAL), | sizeof(STR_SERIAL), | ||||
3, | |||||
3, | |||||
{STR_SERIAL} | {STR_SERIAL} | ||||
}; | }; | ||||
{0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)}, | {0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)}, | ||||
{0x0600, 0x0000, device_qualifier_descriptor, sizeof(device_qualifier_descriptor)}, | {0x0600, 0x0000, device_qualifier_descriptor, sizeof(device_qualifier_descriptor)}, | ||||
{0x0A00, 0x0000, usb_debug_descriptor, sizeof(usb_debug_descriptor)}, | {0x0A00, 0x0000, usb_debug_descriptor, sizeof(usb_debug_descriptor)}, | ||||
{0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)}, | |||||
{0x2100, KEYBOARD_INTERFACE, config_descriptor + KEYBOARD_DESC_OFFSET, 9}, | |||||
{0x2200, NKRO_KEYBOARD_INTERFACE, nkro_keyboard_report_desc, sizeof(nkro_keyboard_report_desc)}, | |||||
{0x2100, NKRO_KEYBOARD_INTERFACE, config_descriptor + NKRO_KEYBOARD_DESC_OFFSET, 9}, | |||||
{0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)}, | |||||
{0x2100, KEYBOARD_INTERFACE, config_descriptor + KEYBOARD_DESC_OFFSET, 9}, | |||||
{0x2200, NKRO_KEYBOARD_INTERFACE, nkro_keyboard_report_desc, sizeof(nkro_keyboard_report_desc)}, | |||||
{0x2100, NKRO_KEYBOARD_INTERFACE, config_descriptor + NKRO_KEYBOARD_DESC_OFFSET, 9}, | |||||
/* MOUSE | /* MOUSE | ||||
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)}, | |||||
{0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9}, | |||||
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)}, | |||||
{0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9}, | |||||
*/ | */ | ||||
{0x0300, 0x0000, (const uint8_t *)&string0, 0}, | |||||
{0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0}, | |||||
{0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0}, | |||||
{0x0303, 0x0409, (const uint8_t *)&usb_string_serial_number, 0}, | |||||
{0x0300, 0x0000, (const uint8_t *)&string0, 0}, | |||||
{0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0}, | |||||
{0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0}, | |||||
{0x0303, 0x0409, (const uint8_t *)&usb_string_serial_number, 0}, | |||||
{0, 0, NULL, 0} | {0, 0, NULL, 0} | ||||
}; | }; | ||||
// ----- Defines ----- | // ----- Defines ----- | ||||
#define ENDPOINT_UNUSED 0x00 | |||||
#define ENDPOINT_TRANSIMIT_ONLY 0x15 | |||||
#define ENDPOINT_RECEIVE_ONLY 0x19 | |||||
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D | |||||
#define ENDPOINT_UNUSED 0x00 | |||||
#define ENDPOINT_TRANSIMIT_ONLY 0x15 | |||||
#define ENDPOINT_RECEIVE_ONLY 0x19 | |||||
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D | |||||
#define DEVICE_CLASS 0x00 // Keep 0x00 to indicate each sub device will indicate what it is | #define DEVICE_CLASS 0x00 // Keep 0x00 to indicate each sub device will indicate what it is | ||||
#define MOUSE_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9) | #define MOUSE_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9) | ||||
#define JOYSTICK_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9+9+7 + 9) | #define JOYSTICK_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9+9+7 + 9) | ||||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY | |||||
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY | |||||
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY | |||||
// ----- Enumerations ----- | // ----- Enumerations ----- | ||||
typedef struct { | typedef struct { | ||||
uint16_t wValue; | |||||
uint16_t wIndex; | |||||
const uint8_t *addr; | |||||
uint16_t length; | |||||
uint16_t wValue; | |||||
uint16_t wIndex; | |||||
const uint8_t *addr; | |||||
uint16_t length; | |||||
} usb_descriptor_list_t; | } usb_descriptor_list_t; | ||||
//#define UART_DEBUG_UNKNOWN 1 | //#define UART_DEBUG_UNKNOWN 1 | ||||
#define TX_STATE_BOTH_FREE_EVEN_FIRST 0 | |||||
#define TX_STATE_BOTH_FREE_ODD_FIRST 1 | |||||
#define TX_STATE_EVEN_FREE 2 | |||||
#define TX_STATE_ODD_FREE 3 | |||||
#define TX_STATE_NONE_FREE_EVEN_FIRST 4 | |||||
#define TX_STATE_NONE_FREE_ODD_FIRST 5 | |||||
#define BDT_OWN 0x80 | |||||
#define BDT_DATA1 0x40 | |||||
#define BDT_DATA0 0x00 | |||||
#define BDT_DTS 0x08 | |||||
#define BDT_STALL 0x04 | |||||
#define TX_STATE_BOTH_FREE_EVEN_FIRST 0 | |||||
#define TX_STATE_BOTH_FREE_ODD_FIRST 1 | |||||
#define TX_STATE_EVEN_FREE 2 | |||||
#define TX_STATE_ODD_FREE 3 | |||||
#define TX_STATE_NONE_FREE_EVEN_FIRST 4 | |||||
#define TX_STATE_NONE_FREE_ODD_FIRST 5 | |||||
#define BDT_OWN 0x80 | |||||
#define BDT_DATA1 0x40 | |||||
#define BDT_DATA0 0x00 | |||||
#define BDT_DTS 0x08 | |||||
#define BDT_STALL 0x04 | |||||
#define TX 1 | #define TX 1 | ||||
#define RX 0 | #define RX 0 | ||||
#define DATA1 1 | #define DATA1 1 | ||||
#define GET_STATUS 0 | |||||
#define CLEAR_FEATURE 1 | |||||
#define SET_FEATURE 3 | |||||
#define SET_ADDRESS 5 | |||||
#define GET_DESCRIPTOR 6 | |||||
#define SET_DESCRIPTOR 7 | |||||
#define GET_CONFIGURATION 8 | |||||
#define SET_CONFIGURATION 9 | |||||
#define GET_INTERFACE 10 | |||||
#define SET_INTERFACE 11 | |||||
#define SYNCH_FRAME 12 | |||||
#define GET_STATUS 0 | |||||
#define CLEAR_FEATURE 1 | |||||
#define SET_FEATURE 3 | |||||
#define SET_ADDRESS 5 | |||||
#define GET_DESCRIPTOR 6 | |||||
#define SET_DESCRIPTOR 7 | |||||
#define GET_CONFIGURATION 8 | |||||
#define SET_CONFIGURATION 9 | |||||
#define GET_INTERFACE 10 | |||||
#define SET_INTERFACE 11 | |||||
#define SYNCH_FRAME 12 | |||||
#define TX_STATE_BOTH_FREE_EVEN_FIRST 0 | |||||
#define TX_STATE_BOTH_FREE_ODD_FIRST 1 | |||||
#define TX_STATE_EVEN_FREE 2 | |||||
#define TX_STATE_ODD_FREE 3 | |||||
#define TX_STATE_NONE_FREE 4 | |||||
#define TX_STATE_BOTH_FREE_EVEN_FIRST 0 | |||||
#define TX_STATE_BOTH_FREE_ODD_FIRST 1 | |||||
#define TX_STATE_EVEN_FREE 2 | |||||
#define TX_STATE_ODD_FREE 3 | |||||
#define TX_STATE_NONE_FREE 4 | |||||
// ----- Macros ----- | // ----- Macros ----- | ||||
#define BDT_PID(n) (((n) >> 2) & 15) | |||||
#define BDT_PID(n) (((n) >> 2) & 15) | |||||
#define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \ | |||||
#define BDT_DESC(count, data) (BDT_OWN | BDT_DTS \ | |||||
| ((data) ? BDT_DATA1 : BDT_DATA0) \ | | ((data) ? BDT_DATA1 : BDT_DATA0) \ | ||||
| ((count) << 16)) | | ((count) << 16)) | ||||
serial_phex(b->desc >> 16); | serial_phex(b->desc >> 16); | ||||
serial_print("\n"); | serial_print("\n"); | ||||
#endif | #endif | ||||
endpoint--; // endpoint is index to zero-based arrays | |||||
endpoint--; // endpoint is index to zero-based arrays | |||||
if ( stat & 0x08 ) | if ( stat & 0x08 ) | ||||
{ // transmit | { // transmit | ||||
// If no USB cable is attached, do not initialize usb | // If no USB cable is attached, do not initialize usb | ||||
// XXX Test -HaaTa | // XXX Test -HaaTa | ||||
//if ( USB0_OTGISTAT & USB_OTGSTAT_ID ) | //if ( USB0_OTGISTAT & USB_OTGSTAT_ID ) | ||||
// return 0; | |||||
// return 0; | |||||
// Clear out endpoints table | // Clear out endpoints table | ||||
for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) |
static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline)); | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline)); | ||||
static inline uint32_t usb_rx_byte_count(uint32_t endpoint) | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) | ||||
{ | { | ||||
endpoint--; | |||||
if ( endpoint >= NUM_ENDPOINTS ) | |||||
endpoint--; | |||||
if ( endpoint >= NUM_ENDPOINTS ) | |||||
return 0; | return 0; | ||||
return usb_rx_byte_count_data[ endpoint ]; | |||||
return usb_rx_byte_count_data[ endpoint ]; | |||||
} | } | ||||
void usb_device_reload(); | void usb_device_reload(); |
// ----- Defines ----- | // ----- Defines ----- | ||||
#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ | |||||
#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ | |||||
// Maximum number of transmit packets to queue so we don't starve other endpoints for memory | // Maximum number of transmit packets to queue so we don't starve other endpoints for memory | ||||
#define TX_PACKET_LIMIT 8 | #define TX_PACKET_LIMIT 8 |
// Check to see if a usb cable has been plugged in | // Check to see if a usb cable has been plugged in | ||||
// XXX Not tested (also, not currently needed) -HaaTa | // XXX Not tested (also, not currently needed) -HaaTa | ||||
//if ( USB0_STAT & (1 << 1) | //if ( USB0_STAT & (1 << 1) | ||||
// return 0; | |||||
// return 0; | |||||
HW_CONFIG(); | HW_CONFIG(); | ||||
USB_FREEZE(); // enable USB | |||||
PLL_CONFIG(); // config PLL | |||||
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock | |||||
USB_CONFIG(); // start USB clock | |||||
UDCON = 0; // enable attach resistor | |||||
USB_FREEZE(); // enable USB | |||||
PLL_CONFIG(); // config PLL | |||||
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock | |||||
USB_CONFIG(); // start USB clock | |||||
UDCON = 0; // enable attach resistor | |||||
usb_configuration = 0; | usb_configuration = 0; | ||||
UDIEN = (1<<EORSTE) | (1<<SOFE); | |||||
UDIEN = (1<<EORSTE) | (1<<SOFE); | |||||
sei(); | sei(); | ||||
// Disable watchdog timer after possible software reset | // Disable watchdog timer after possible software reset | ||||
{ | { | ||||
uint8_t intbits, t_cdc; | uint8_t intbits, t_cdc; | ||||
intbits = UDINT; | |||||
UDINT = 0; | |||||
if ( intbits & (1 << EORSTI) ) | |||||
intbits = UDINT; | |||||
UDINT = 0; | |||||
if ( intbits & (1 << EORSTI) ) | |||||
{ | { | ||||
UENUM = 0; | UENUM = 0; | ||||
UECONX = 1; | UECONX = 1; | ||||
UEIENX = (1 << RXSTPE); | UEIENX = (1 << RXSTPE); | ||||
usb_configuration = 0; | usb_configuration = 0; | ||||
cdc_line_rtsdtr = 0; | cdc_line_rtsdtr = 0; | ||||
} | |||||
} | |||||
if ( (intbits & (1 << SOFI)) && usb_configuration ) | if ( (intbits & (1 << SOFI)) && usb_configuration ) | ||||
{ | { | ||||
t_cdc = transmit_flush_timer; | t_cdc = transmit_flush_timer; | ||||
// | // | ||||
ISR( USB_COM_vect ) | ISR( USB_COM_vect ) | ||||
{ | { | ||||
uint8_t intbits; | |||||
uint8_t intbits; | |||||
const uint8_t *list; | const uint8_t *list; | ||||
const uint8_t *cfg; | |||||
const uint8_t *cfg; | |||||
uint8_t i, n, len, en; | uint8_t i, n, len, en; | ||||
uint8_t *p; | uint8_t *p; | ||||
uint8_t bmRequestType; | uint8_t bmRequestType; | ||||
uint16_t wLength; | uint16_t wLength; | ||||
uint16_t desc_val; | uint16_t desc_val; | ||||
const uint8_t *desc_addr; | const uint8_t *desc_addr; | ||||
uint8_t desc_length; | |||||
uint8_t desc_length; | |||||
UENUM = 0; | |||||
UENUM = 0; | |||||
intbits = UEINTX; | intbits = UEINTX; | ||||
if (intbits & (1<<RXSTPI)) | if (intbits & (1<<RXSTPI)) | ||||
{ | { | ||||
bmRequestType = UEDATX; | |||||
bRequest = UEDATX; | |||||
wValue = UEDATX; | |||||
wValue |= (UEDATX << 8); | |||||
wIndex = UEDATX; | |||||
wIndex |= (UEDATX << 8); | |||||
wLength = UEDATX; | |||||
wLength |= (UEDATX << 8); | |||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); | |||||
if ( bRequest == GET_DESCRIPTOR ) | |||||
bmRequestType = UEDATX; | |||||
bRequest = UEDATX; | |||||
wValue = UEDATX; | |||||
wValue |= (UEDATX << 8); | |||||
wIndex = UEDATX; | |||||
wIndex |= (UEDATX << 8); | |||||
wLength = UEDATX; | |||||
wLength |= (UEDATX << 8); | |||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); | |||||
if ( bRequest == GET_DESCRIPTOR ) | |||||
{ | { | ||||
list = (const uint8_t *)descriptor_list; | list = (const uint8_t *)descriptor_list; | ||||
for ( i = 0; ; i++ ) | for ( i = 0; ; i++ ) | ||||
do { | do { | ||||
i = UEINTX; | i = UEINTX; | ||||
} while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); | } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); | ||||
if (i & (1<<RXOUTI)) return; // abort | |||||
if (i & (1<<RXOUTI)) return; // abort | |||||
// send IN packet | // send IN packet | ||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; | n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; | ||||
for (i = n; i; i--) { | for (i = n; i; i--) { | ||||
usb_send_in(); | usb_send_in(); | ||||
} while (len || n == ENDPOINT0_SIZE); | } while (len || n == ENDPOINT0_SIZE); | ||||
return; | return; | ||||
} | |||||
} | |||||
if (bRequest == SET_ADDRESS) { | if (bRequest == SET_ADDRESS) { | ||||
usb_send_in(); | usb_send_in(); | ||||
UECFG1X = pgm_read_byte(cfg++); | UECFG1X = pgm_read_byte(cfg++); | ||||
} | } | ||||
} | } | ||||
UERST = 0x7E; | |||||
UERST = 0; | |||||
UERST = 0x7E; | |||||
UERST = 0; | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
UECONX = (1 << STALLRQ) | (1 << EPEN); // stall | |||||
UECONX = (1 << STALLRQ) | (1 << EPEN); // stall | |||||
} | } | ||||
// ----- Function Declarations ----- | // ----- Function Declarations ----- | ||||
// Basic USB Configuration | // Basic USB Configuration | ||||
uint8_t usb_init(); // initialize everything | |||||
uint8_t usb_configured(); // is the USB port configured | |||||
uint8_t usb_init(); // initialize everything | |||||
uint8_t usb_configured(); // is the USB port configured | |||||
// Keyboard HID Functions | // Keyboard HID Functions | ||||
void usb_keyboard_send(); | void usb_keyboard_send(); | ||||
void usb_device_reload(); // Enable firmware reflash mode | void usb_device_reload(); // Enable firmware reflash mode | ||||
// USB Serial CDC Functions | // USB Serial CDC Functions | ||||
int16_t usb_serial_getchar(); // receive a character (-1 if timeout/error) | |||||
uint8_t usb_serial_available(); // number of bytes in receive buffer | |||||
void usb_serial_flush_input(); // discard any buffered input | |||||
int16_t usb_serial_getchar(); // receive a character (-1 if timeout/error) | |||||
uint8_t usb_serial_available(); // number of bytes in receive buffer | |||||
void usb_serial_flush_input(); // discard any buffered input | |||||
// transmitting data | // transmitting data | ||||
int8_t usb_serial_putchar(uint8_t c); // transmit a character | int8_t usb_serial_putchar(uint8_t c); // transmit a character | ||||
#define usb_device_software_reset() do { wdt_enable( WDTO_15MS ); for(;;); } while(0) | #define usb_device_software_reset() do { wdt_enable( WDTO_15MS ); for(;;); } while(0) | ||||
// See EPSIZE -> UECFG1X - 128 and 256 bytes are for endpoint 1 only | // See EPSIZE -> UECFG1X - 128 and 256 bytes are for endpoint 1 only | ||||
#define EP_SIZE(s) ((s) == 256 ? 0x50 : \ | |||||
#define EP_SIZE(s) ((s) == 256 ? 0x50 : \ | |||||
((s) == 128 ? 0x40 : \ | ((s) == 128 ? 0x40 : \ | ||||
((s) == 64 ? 0x30 : \ | ((s) == 64 ? 0x30 : \ | ||||
((s) == 32 ? 0x20 : \ | ((s) == 32 ? 0x20 : \ | ||||
// ----- Defines ----- | // ----- Defines ----- | ||||
// constants corresponding to the various serial parameters | // constants corresponding to the various serial parameters | ||||
#define USB_SERIAL_DTR 0x01 | |||||
#define USB_SERIAL_RTS 0x02 | |||||
#define USB_SERIAL_1_STOP 0 | |||||
#define USB_SERIAL_1_5_STOP 1 | |||||
#define USB_SERIAL_2_STOP 2 | |||||
#define USB_SERIAL_PARITY_NONE 0 | |||||
#define USB_SERIAL_PARITY_ODD 1 | |||||
#define USB_SERIAL_PARITY_EVEN 2 | |||||
#define USB_SERIAL_PARITY_MARK 3 | |||||
#define USB_SERIAL_PARITY_SPACE 4 | |||||
#define USB_SERIAL_DCD 0x01 | |||||
#define USB_SERIAL_DSR 0x02 | |||||
#define USB_SERIAL_BREAK 0x04 | |||||
#define USB_SERIAL_RI 0x08 | |||||
#define USB_SERIAL_FRAME_ERR 0x10 | |||||
#define USB_SERIAL_PARITY_ERR 0x20 | |||||
#define USB_SERIAL_OVERRUN_ERR 0x40 | |||||
#define EP_TYPE_CONTROL 0x00 | |||||
#define EP_TYPE_BULK_IN 0x81 | |||||
#define EP_TYPE_BULK_OUT 0x80 | |||||
#define EP_TYPE_INTERRUPT_IN 0xC1 | |||||
#define EP_TYPE_INTERRUPT_OUT 0xC0 | |||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41 | |||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40 | |||||
#define EP_SINGLE_BUFFER 0x02 | |||||
#define EP_DOUBLE_BUFFER 0x06 | |||||
#define MAX_ENDPOINT 4 | |||||
#define USB_SERIAL_DTR 0x01 | |||||
#define USB_SERIAL_RTS 0x02 | |||||
#define USB_SERIAL_1_STOP 0 | |||||
#define USB_SERIAL_1_5_STOP 1 | |||||
#define USB_SERIAL_2_STOP 2 | |||||
#define USB_SERIAL_PARITY_NONE 0 | |||||
#define USB_SERIAL_PARITY_ODD 1 | |||||
#define USB_SERIAL_PARITY_EVEN 2 | |||||
#define USB_SERIAL_PARITY_MARK 3 | |||||
#define USB_SERIAL_PARITY_SPACE 4 | |||||
#define USB_SERIAL_DCD 0x01 | |||||
#define USB_SERIAL_DSR 0x02 | |||||
#define USB_SERIAL_BREAK 0x04 | |||||
#define USB_SERIAL_RI 0x08 | |||||
#define USB_SERIAL_FRAME_ERR 0x10 | |||||
#define USB_SERIAL_PARITY_ERR 0x20 | |||||
#define USB_SERIAL_OVERRUN_ERR 0x40 | |||||
#define EP_TYPE_CONTROL 0x00 | |||||
#define EP_TYPE_BULK_IN 0x81 | |||||
#define EP_TYPE_BULK_OUT 0x80 | |||||
#define EP_TYPE_INTERRUPT_IN 0xC1 | |||||
#define EP_TYPE_INTERRUPT_OUT 0xC0 | |||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41 | |||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40 | |||||
#define EP_SINGLE_BUFFER 0x02 | |||||
#define EP_DOUBLE_BUFFER 0x06 | |||||
#define MAX_ENDPOINT 4 | |||||
#if defined(__AVR_AT90USB162__) | #if defined(__AVR_AT90USB162__) | ||||
#define HW_CONFIG() | #define HW_CONFIG() | ||||
#endif | #endif | ||||
// standard control endpoint request types | // standard control endpoint request types | ||||
#define GET_STATUS 0 | |||||
#define CLEAR_FEATURE 1 | |||||
#define SET_FEATURE 3 | |||||
#define SET_ADDRESS 5 | |||||
#define GET_DESCRIPTOR 6 | |||||
#define GET_CONFIGURATION 8 | |||||
#define SET_CONFIGURATION 9 | |||||
#define GET_INTERFACE 10 | |||||
#define SET_INTERFACE 11 | |||||
#define GET_STATUS 0 | |||||
#define CLEAR_FEATURE 1 | |||||
#define SET_FEATURE 3 | |||||
#define SET_ADDRESS 5 | |||||
#define GET_DESCRIPTOR 6 | |||||
#define GET_CONFIGURATION 8 | |||||
#define SET_CONFIGURATION 9 | |||||
#define GET_INTERFACE 10 | |||||
#define SET_INTERFACE 11 | |||||
// HID (human interface device) | // HID (human interface device) | ||||
#define HID_GET_REPORT 1 | |||||
#define HID_GET_IDLE 2 | |||||
#define HID_GET_PROTOCOL 3 | |||||
#define HID_SET_REPORT 9 | |||||
#define HID_SET_IDLE 10 | |||||
#define HID_SET_PROTOCOL 11 | |||||
#define HID_GET_REPORT 1 | |||||
#define HID_GET_IDLE 2 | |||||
#define HID_GET_PROTOCOL 3 | |||||
#define HID_SET_REPORT 9 | |||||
#define HID_SET_IDLE 10 | |||||
#define HID_SET_PROTOCOL 11 | |||||
// CDC (communication class device) | // CDC (communication class device) | ||||
#define CDC_SET_LINE_CODING 0x20 | |||||
#define CDC_GET_LINE_CODING 0x21 | |||||
#define CDC_SET_CONTROL_LINE_STATE 0x22 | |||||
#define CDC_SET_LINE_CODING 0x20 | |||||
#define CDC_GET_LINE_CODING 0x21 | |||||
#define CDC_SET_CONTROL_LINE_STATE 0x22 | |||||
// CDC Configuration | // CDC Configuration | ||||
// When you write data, it goes into a USB endpoint buffer, which | // When you write data, it goes into a USB endpoint buffer, which | ||||
// that tells the PC no more data is expected and it should pass | // that tells the PC no more data is expected and it should pass | ||||
// any buffered data to the application that may be waiting. If | // any buffered data to the application that may be waiting. If | ||||
// you want data sent immediately, call usb_serial_flush_output(). | // you want data sent immediately, call usb_serial_flush_output(). | ||||
#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ | |||||
#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */ | |||||
// If the PC is connected but not "listening", this is the length | // If the PC is connected but not "listening", this is the length | ||||
// of time before usb_serial_getchar() returns with an error. This | // of time before usb_serial_getchar() returns with an error. This | ||||
// bits on a wire where nobody is listening, except you get an error | // bits on a wire where nobody is listening, except you get an error | ||||
// code which you can ignore for serial-like discard of data, or | // code which you can ignore for serial-like discard of data, or | ||||
// use to know your data wasn't sent. | // use to know your data wasn't sent. | ||||
#define TRANSMIT_TIMEOUT 25 /* in milliseconds */ | |||||
#define TRANSMIT_TIMEOUT 25 /* in milliseconds */ | |||||
// ----- Endpoint Configuration ----- | // ----- Endpoint Configuration ----- | ||||
#define ENDPOINT0_SIZE 32 | |||||
#define ENDPOINT0_SIZE 32 | |||||
#define KEYBOARD_NKRO_INTERFACE 0 | #define KEYBOARD_NKRO_INTERFACE 0 | ||||
#define KEYBOARD_NKRO_ENDPOINT 1 | #define KEYBOARD_NKRO_ENDPOINT 1 | ||||
#define KEYBOARD_INTERFACE 1 | #define KEYBOARD_INTERFACE 1 | ||||
#define KEYBOARD_ENDPOINT 2 | #define KEYBOARD_ENDPOINT 2 | ||||
#define KEYBOARD_SIZE 8 | |||||
#define KEYBOARD_SIZE 8 | |||||
#define KEYBOARD_HID_BUFFER EP_DOUBLE_BUFFER | #define KEYBOARD_HID_BUFFER EP_DOUBLE_BUFFER | ||||
#define CDC_IAD_DESCRIPTOR 1 | #define CDC_IAD_DESCRIPTOR 1 | ||||
#define CDC_STATUS_INTERFACE 2 | #define CDC_STATUS_INTERFACE 2 | ||||
#define CDC_DATA_INTERFACE 3 | #define CDC_DATA_INTERFACE 3 | ||||
#define CDC_ACM_ENDPOINT 3 | #define CDC_ACM_ENDPOINT 3 | ||||
#define CDC_RX_ENDPOINT 4 | |||||
#define CDC_TX_ENDPOINT 5 | |||||
#define CDC_RX_ENDPOINT 4 | |||||
#define CDC_TX_ENDPOINT 5 | |||||
#if defined(__AVR_AT90USB162__) | #if defined(__AVR_AT90USB162__) | ||||
#define CDC_ACM_SIZE 16 | |||||
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER | |||||
#define CDC_RX_SIZE 32 | |||||
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_TX_SIZE 32 | |||||
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_ACM_SIZE 16 | |||||
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER | |||||
#define CDC_RX_SIZE 32 | |||||
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_TX_SIZE 32 | |||||
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER | |||||
#else | #else | ||||
#define CDC_ACM_SIZE 16 | |||||
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER | |||||
#define CDC_RX_SIZE 64 | |||||
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_TX_SIZE 64 | |||||
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_ACM_SIZE 16 | |||||
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER | |||||
#define CDC_RX_SIZE 64 | |||||
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER | |||||
#define CDC_TX_SIZE 64 | |||||
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER | |||||
#endif | #endif | ||||
// Endpoint 0 is reserved for the control endpoint | // Endpoint 0 is reserved for the control endpoint | ||||
static const uint8_t PROGMEM device_descriptor[] = { | static const uint8_t PROGMEM device_descriptor[] = { | ||||
18, // bLength | |||||
1, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
0x00, // bDeviceClass - Composite device, 0x00 is required for Windows | |||||
0, // bDeviceSubClass | |||||
0, // bDeviceProtocol | |||||
ENDPOINT0_SIZE, // bMaxPacketSize0 | |||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | |||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | |||||
0x00, 0x01, // bcdDevice | |||||
1, // iManufacturer | |||||
2, // iProduct | |||||
3, // iSerialNumber | |||||
1 // bNumConfigurations | |||||
18, // bLength | |||||
1, // bDescriptorType | |||||
0x00, 0x02, // bcdUSB | |||||
0x00, // bDeviceClass - Composite device, 0x00 is required for Windows | |||||
0, // bDeviceSubClass | |||||
0, // bDeviceProtocol | |||||
ENDPOINT0_SIZE, // bMaxPacketSize0 | |||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | |||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | |||||
0x00, 0x01, // bcdDevice | |||||
1, // iManufacturer | |||||
2, // iProduct | |||||
3, // iSerialNumber | |||||
1 // bNumConfigurations | |||||
}; | }; | ||||
// Specify only a single USB speed | // Specify only a single USB speed | ||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||||
static const uint8_t PROGMEM keyboard_hid_report_desc[] = { | static const uint8_t PROGMEM keyboard_hid_report_desc[] = { | ||||
// Keyboard Collection | // Keyboard Collection | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
// Modifier Byte | // Modifier Byte | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
// Reserved Byte | // Reserved Byte | ||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x03, // Output (Constant), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x81, 0x03, // Output (Constant), | |||||
// LED Report | // LED Report | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
// LED Report Padding | // LED Report Padding | ||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
// Normal Keys | // Normal Keys | ||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x06, // Report Count (6), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x7F, // Logical Maximum(104), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, 0x7F, // Usage Maximum (104), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Keyboard | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x06, // Report Count (6), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x7F, // Logical Maximum(104), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x00, // Usage Minimum (0), | |||||
0x29, 0x7F, // Usage Maximum (104), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Keyboard | |||||
}; | }; | ||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||||
static const uint8_t PROGMEM keyboard_nkro_hid_report_desc[] = { | static const uint8_t PROGMEM keyboard_nkro_hid_report_desc[] = { | ||||
// Keyboard Collection | // Keyboard Collection | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x06, // Usage (Keyboard), | |||||
0xA1, 0x01, // Collection (Application) - Keyboard, | |||||
// LED Report | // LED Report | ||||
0x85, 0x01, // Report ID (1), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
0x85, 0x01, // Report ID (1), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x05, // Report Count (5), | |||||
0x05, 0x08, // Usage Page (LEDs), | |||||
0x19, 0x01, // Usage Minimum (1), | |||||
0x29, 0x05, // Usage Maximum (5), | |||||
0x91, 0x02, // Output (Data, Variable, Absolute), | |||||
// LED Report Padding | // LED Report Padding | ||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
0x75, 0x03, // Report Size (3), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x91, 0x03, // Output (Constant), | |||||
// Normal Keys - Using an NKRO Bitmap | // Normal Keys - Using an NKRO Bitmap | ||||
// | // | ||||
// 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) | // 224-231 : 1 byte (0xE0-0xE7) ( 8 bits) | ||||
// Modifier Byte | // Modifier Byte | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xE0, // Usage Minimum (224), | |||||
0x29, 0xE7, // Usage Maximum (231), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute), | |||||
// 4-49 (6 bytes/46 bits) - MainKeys | // 4-49 (6 bytes/46 bits) - MainKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x04, // Usage Minimum (4), | |||||
0x29, 0x31, // Usage Maximum (49), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x04, // Usage Minimum (4), | |||||
0x29, 0x31, // Usage Maximum (49), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (2 bits) | // Padding (2 bits) | ||||
0x75, 0x02, // Report Size (2), | 0x75, 0x02, // Report Size (2), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
// 51-155 (14 bytes/105 bits) - SecondaryKeys | // 51-155 (14 bytes/105 bits) - SecondaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x69, // Report Count (105), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x33, // Usage Minimum (51), | |||||
0x29, 0x9B, // Usage Maximum (155), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x69, // Report Count (105), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x33, // Usage Minimum (51), | |||||
0x29, 0x9B, // Usage Maximum (155), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (7 bits) | // Padding (7 bits) | ||||
0x75, 0x07, // Report Size (7), | 0x75, 0x07, // Report Size (7), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
// 157-164 (1 byte/8 bits) - TertiaryKeys | // 157-164 (1 byte/8 bits) - TertiaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x9D, // Usage Minimum (157), | |||||
0x29, 0xA4, // Usage Maximum (164), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x08, // Report Count (8), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0x9D, // Usage Minimum (157), | |||||
0x29, 0xA4, // Usage Maximum (164), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// 176-221 (6 bytes/46 bits) - QuartiaryKeys | // 176-221 (6 bytes/46 bits) - QuartiaryKeys | ||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xB0, // Usage Minimum (176), | |||||
0x29, 0xDD, // Usage Maximum (221), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
0x75, 0x01, // Report Size (1), | |||||
0x95, 0x2E, // Report Count (46), | |||||
0x15, 0x00, // Logical Minimum (0), | |||||
0x25, 0x01, // Logical Maximum (1), | |||||
0x05, 0x07, // Usage Page (Key Codes), | |||||
0x19, 0xB0, // Usage Minimum (176), | |||||
0x29, 0xDD, // Usage Maximum (221), | |||||
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield), | |||||
// Padding (2 bits) | // Padding (2 bits) | ||||
0x75, 0x02, // Report Size (2), | 0x75, 0x02, // Report Size (2), | ||||
0x95, 0x01, // Report Count (1), | 0x95, 0x01, // Report Count (1), | ||||
0x81, 0x03, // Input (Constant), | 0x81, 0x03, // Input (Constant), | ||||
0xc0, // End Collection - Keyboard | |||||
0xc0, // End Collection - Keyboard | |||||
// System Control Collection | // System Control Collection | ||||
// | // | ||||
// NOTES: | // NOTES: | ||||
// Not bothering with NKRO for this table. If there's need, I can implement it. -HaaTa | // Not bothering with NKRO for this table. If there's need, I can implement it. -HaaTa | ||||
// Using a 1KRO scheme | // Using a 1KRO scheme | ||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x80, // Usage (System Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x02, // Report ID (2), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x81, 0x00, // Logical Minimum (129), | |||||
0x26, 0xB7, 0x00, // Logical Maximum (183), | |||||
0x19, 0x81, // Usage Minimum (129), | |||||
0x29, 0xB7, // Usage Maximum (183), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - System Control | |||||
0x05, 0x01, // Usage Page (Generic Desktop), | |||||
0x09, 0x80, // Usage (System Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x02, // Report ID (2), | |||||
0x75, 0x08, // Report Size (8), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x81, 0x00, // Logical Minimum (129), | |||||
0x26, 0xB7, 0x00, // Logical Maximum (183), | |||||
0x19, 0x81, // Usage Minimum (129), | |||||
0x29, 0xB7, // Usage Maximum (183), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - System Control | |||||
// Consumer Control Collection - Media Keys | // Consumer Control Collection - Media Keys | ||||
// | // | ||||
// NOTES: | // NOTES: | ||||
// Not bothering with NKRO for this table. If there's a need, I can implement it. -HaaTa | // Not bothering with NKRO for this table. If there's a need, I can implement it. -HaaTa | ||||
// Using a 1KRO scheme | // Using a 1KRO scheme | ||||
0x05, 0x0c, // Usage Page (Consumer), | |||||
0x09, 0x01, // Usage (Consumer Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x03, // Report ID (3), | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x20, 0x00, // Logical Minimum (32), | |||||
0x26, 0x9C, 0x02, // Logical Maximum (668), | |||||
0x05, 0x0C, // Usage Page (Consumer), | |||||
0x19, 0x20, // Usage Minimum (32), | |||||
0x2A, 0x9C, 0x02, // Usage Maximum (668), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Consumer Control | |||||
0x05, 0x0c, // Usage Page (Consumer), | |||||
0x09, 0x01, // Usage (Consumer Control), | |||||
0xA1, 0x01, // Collection (Application), | |||||
0x85, 0x03, // Report ID (3), | |||||
0x75, 0x10, // Report Size (16), | |||||
0x95, 0x01, // Report Count (1), | |||||
0x16, 0x20, 0x00, // Logical Minimum (32), | |||||
0x26, 0x9C, 0x02, // Logical Maximum (668), | |||||
0x05, 0x0C, // Usage Page (Consumer), | |||||
0x19, 0x20, // Usage Minimum (32), | |||||
0x2A, 0x9C, 0x02, // Usage Maximum (668), | |||||
0x81, 0x00, // Input (Data, Array), | |||||
0xc0, // End Collection - Consumer Control | |||||
}; | }; | ||||
// <Configuration> + <Keyboard HID> + <NKRO Keyboard HID> + <Serial CDC> | // <Configuration> + <Keyboard HID> + <NKRO Keyboard HID> + <Serial CDC> | ||||
// --- Configuration --- | // --- Configuration --- | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | ||||
9, // bLength; | |||||
2, // bDescriptorType; | |||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength | |||||
9, // bLength; | |||||
2, // bDescriptorType; | |||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength | |||||
MSB(CONFIG1_DESC_SIZE), | MSB(CONFIG1_DESC_SIZE), | ||||
4, // bNumInterfaces | |||||
1, // bConfigurationValue | |||||
0, // iConfiguration | |||||
0x80, // bmAttributes | |||||
250, // bMaxPower | |||||
4, // bNumInterfaces | |||||
1, // bConfigurationValue | |||||
0, // iConfiguration | |||||
0x80, // bmAttributes | |||||
250, // bMaxPower | |||||
// --- Keyboard HID --- | // --- Keyboard HID --- | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | // HID interface descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode - Setting to 0/Undefined | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(keyboard_hid_report_desc)), // wDescriptorLength | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode - Setting to 0/Undefined | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
LSB(sizeof(keyboard_hid_report_desc)), // wDescriptorLength | |||||
MSB(sizeof(keyboard_hid_report_desc)), | MSB(sizeof(keyboard_hid_report_desc)), | ||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
1, // bInterval | 1, // bInterval | ||||
// --- NKRO Keyboard HID --- | // --- NKRO Keyboard HID --- | ||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_NKRO_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_NKRO_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot) | |||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | |||||
0, // iInterface | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | // HID interface descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode - Setting to 0/Undefined | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
// wDescriptorLength | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode - Setting to 0/Undefined | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
// wDescriptorLength | |||||
LSB(sizeof(keyboard_nkro_hid_report_desc)), | LSB(sizeof(keyboard_nkro_hid_report_desc)), | ||||
MSB(sizeof(keyboard_nkro_hid_report_desc)), | MSB(sizeof(keyboard_nkro_hid_report_desc)), | ||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_NKRO_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_NKRO_SIZE, 0, // wMaxPacketSize | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_NKRO_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_NKRO_SIZE, 0, // wMaxPacketSize | |||||
1, // bInterval | 1, // bInterval | ||||
// --- Serial CDC --- | // --- Serial CDC --- | ||||
// - 8 bytes - | // - 8 bytes - | ||||
// interface association descriptor, USB ECN, Table 9-Z | |||||
8, // bLength | |||||
11, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bFirstInterface | |||||
2, // bInterfaceCount | |||||
0x02, // bFunctionClass | |||||
0x02, // bFunctionSubClass | |||||
0x01, // bFunctionProtocol | |||||
4, // iFunction | |||||
// interface association descriptor, USB ECN, Table 9-Z | |||||
8, // bLength | |||||
11, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bFirstInterface | |||||
2, // bInterfaceCount | |||||
0x02, // bFunctionClass | |||||
0x02, // bFunctionSubClass | |||||
0x01, // bFunctionProtocol | |||||
4, // iFunction | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x02, // bInterfaceClass | |||||
0x02, // bInterfaceSubClass | |||||
0x01, // bInterfaceProtocol | |||||
0, // iInterface | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_STATUS_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x02, // bInterfaceClass | |||||
0x02, // bInterfaceSubClass | |||||
0x01, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | ||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x00, // bDescriptorSubtype | |||||
0x10, 0x01, // bcdCDC | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x00, // bDescriptorSubtype | |||||
0x10, 0x01, // bcdCDC | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | ||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x01, // bDescriptorSubtype | |||||
0x01, // bmCapabilities | |||||
1, // bDataInterface | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x01, // bDescriptorSubtype | |||||
0x01, // bmCapabilities | |||||
1, // bDataInterface | |||||
// - 4 bytes - | // - 4 bytes - | ||||
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | ||||
4, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x02, // bDescriptorSubtype | |||||
0x06, // bmCapabilities | |||||
4, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x02, // bDescriptorSubtype | |||||
0x06, // bmCapabilities | |||||
// - 5 bytes - | // - 5 bytes - | ||||
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | ||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x06, // bDescriptorSubtype | |||||
CDC_STATUS_INTERFACE, // bMasterInterface | |||||
CDC_DATA_INTERFACE, // bSlaveInterface0 | |||||
5, // bFunctionLength | |||||
0x24, // bDescriptorType | |||||
0x06, // bDescriptorSubtype | |||||
CDC_STATUS_INTERFACE, // bMasterInterface | |||||
CDC_DATA_INTERFACE, // bSlaveInterface0 | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
CDC_ACM_SIZE, 0, // wMaxPacketSize | |||||
64, // bInterval | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_ACM_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
CDC_ACM_SIZE, 0, // wMaxPacketSize | |||||
64, // bInterval | |||||
// - 9 bytes - | // - 9 bytes - | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_DATA_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
2, // bNumEndpoints | |||||
0x0A, // bInterfaceClass | |||||
0x00, // bInterfaceSubClass | |||||
0x00, // bInterfaceProtocol | |||||
0, // iInterface | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
CDC_DATA_INTERFACE, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
2, // bNumEndpoints | |||||
0x0A, // bInterfaceClass | |||||
0x00, // bInterfaceSubClass | |||||
0x00, // bInterfaceProtocol | |||||
0, // iInterface | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_RX_ENDPOINT, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_RX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_RX_ENDPOINT, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_RX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
// - 7 bytes - | // - 7 bytes - | ||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_TX_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_TX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
CDC_TX_ENDPOINT | 0x80, // bEndpointAddress | |||||
0x02, // bmAttributes (0x02=bulk) | |||||
CDC_TX_SIZE, 0, // wMaxPacketSize | |||||
0, // bInterval | |||||
}; | }; | ||||
// This table defines which descriptor data is sent for each specific | // This table defines which descriptor data is sent for each specific | ||||
// request from the host (in wValue and wIndex). | // request from the host (in wValue and wIndex). | ||||
static const struct descriptor_list_struct { | static const struct descriptor_list_struct { | ||||
uint16_t wValue; | |||||
uint16_t wIndex; | |||||
const uint8_t *addr; | |||||
uint8_t length; | |||||
uint16_t wValue; | |||||
uint16_t wIndex; | |||||
const uint8_t *addr; | |||||
uint8_t length; | |||||
} PROGMEM descriptor_list[] = { | } PROGMEM descriptor_list[] = { | ||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | ||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, | {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, |
// Which modifier keys are currently pressed | // Which modifier keys are currently pressed | ||||
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | ||||
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | ||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
// Currently pressed keys, max is defined by USB_MAX_KEY_SEND | // Currently pressed keys, max is defined by USB_MAX_KEY_SEND | ||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
// System Control and Consumer Control 1KRO containers | // System Control and Consumer Control 1KRO containers | ||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
// The number of keys sent to the usb in the array | // The number of keys sent to the usb in the array | ||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | ||||
volatile uint8_t USBKeys_LEDs = 0; | volatile uint8_t USBKeys_LEDs = 0; | ||||
// the idle configuration, how often we send the report to the | // the idle configuration, how often we send the report to the | ||||
// host (ms * 4) even when it hasn't changed | // host (ms * 4) even when it hasn't changed | ||||
uint8_t USBKeys_Idle_Config = 125; | |||||
uint8_t USBKeys_Idle_Config = 125; | |||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | |||||
uint8_t USBKeys_Idle_Count = 0; | |||||
// Indicates whether the Output module is fully functional | // Indicates whether the Output module is fully functional | ||||
// 0 - Not fully functional, 1 - Fully functional | // 0 - Not fully functional, 1 - Fully functional | ||||
// 0 is often used to show that a USB cable is not plugged in (but has power) | // 0 is often used to show that a USB cable is not plugged in (but has power) | ||||
uint8_t Output_Available = 0; | |||||
uint8_t Output_Available = 0; | |||||
// Debug control variable for Output modules | // Debug control variable for Output modules | ||||
// 0 - Debug disabled (default) | // 0 - Debug disabled (default) | ||||
// 1 - Debug enabled | // 1 - Debug enabled | ||||
uint8_t Output_DebugMode = 0; | |||||
uint8_t Output_DebugMode = 0; | |||||
// Which modifier keys are currently pressed | // Which modifier keys are currently pressed | ||||
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | ||||
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | ||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
// Currently pressed keys, max is defined by USB_MAX_KEY_SEND | // Currently pressed keys, max is defined by USB_MAX_KEY_SEND | ||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
// System Control and Consumer Control 1KRO containers | // System Control and Consumer Control 1KRO containers | ||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
// The number of keys sent to the usb in the array | // The number of keys sent to the usb in the array | ||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | ||||
volatile uint8_t USBKeys_LEDs = 0; | volatile uint8_t USBKeys_LEDs = 0; | ||||
// the idle configuration, how often we send the report to the | // the idle configuration, how often we send the report to the | ||||
// host (ms * 4) even when it hasn't changed | // host (ms * 4) even when it hasn't changed | ||||
uint8_t USBKeys_Idle_Config = 125; | |||||
uint8_t USBKeys_Idle_Config = 125; | |||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | |||||
uint8_t USBKeys_Idle_Count = 0; | |||||
// Indicates whether the Output module is fully functional | // Indicates whether the Output module is fully functional | ||||
// 0 - Not fully functional, 1 - Fully functional | // 0 - Not fully functional, 1 - Fully functional | ||||
// 0 is often used to show that a USB cable is not plugged in (but has power) | // 0 is often used to show that a USB cable is not plugged in (but has power) | ||||
uint8_t Output_Available = 0; | |||||
uint8_t Output_Available = 0; | |||||
// Which modifier keys are currently pressed | // Which modifier keys are currently pressed | ||||
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui | ||||
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui | ||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
uint8_t USBKeys_Modifiers = 0; | |||||
uint8_t USBKeys_ModifiersCLI = 0; // Separate CLI send buffer | |||||
// Currently pressed keys, max is defined by USB_MAX_KEY_SEND | // Currently pressed keys, max is defined by USB_MAX_KEY_SEND | ||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
uint8_t USBKeys_Keys [USB_NKRO_BITFIELD_SIZE_KEYS]; | |||||
uint8_t USBKeys_KeysCLI[USB_NKRO_BITFIELD_SIZE_KEYS]; // Separate CLI send buffer | |||||
// System Control and Consumer Control 1KRO containers | // System Control and Consumer Control 1KRO containers | ||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
uint8_t USBKeys_SysCtrl; | |||||
uint16_t USBKeys_ConsCtrl; | |||||
// The number of keys sent to the usb in the array | // The number of keys sent to the usb in the array | ||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
uint8_t USBKeys_Sent = 0; | |||||
uint8_t USBKeys_SentCLI = 0; | |||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | // 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | ||||
volatile uint8_t USBKeys_LEDs = 0; | volatile uint8_t USBKeys_LEDs = 0; | ||||
// the idle configuration, how often we send the report to the | // the idle configuration, how often we send the report to the | ||||
// host (ms * 4) even when it hasn't changed | // host (ms * 4) even when it hasn't changed | ||||
uint8_t USBKeys_Idle_Config = 125; | |||||
uint8_t USBKeys_Idle_Config = 125; | |||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | |||||
uint8_t USBKeys_Idle_Count = 0; | |||||
// Indicates whether the Output module is fully functional | // Indicates whether the Output module is fully functional | ||||
// 0 - Not fully functional, 1 - Fully functional | // 0 - Not fully functional, 1 - Fully functional | ||||
// 0 is often used to show that a USB cable is not plugged in (but has power) | // 0 is often used to show that a USB cable is not plugged in (but has power) | ||||
uint8_t Output_Available = 0; | |||||
uint8_t Output_Available = 0; | |||||
// Debug control variable for Output modules | // Debug control variable for Output modules | ||||
// 0 - Debug disabled (default) | // 0 - Debug disabled (default) | ||||
// 1 - Debug enabled | // 1 - Debug enabled | ||||
uint8_t Output_DebugMode = 0; | |||||
uint8_t Output_DebugMode = 0; | |||||
# | # | ||||
set( ModuleCompatibility | set( ModuleCompatibility | ||||
arm | arm | ||||
# avr # TODO | |||||
# avr # TODO | |||||
) | ) | ||||
If stuff is hard to read (you have a dumb colour scheme): | If stuff is hard to read (you have a dumb colour scheme): | ||||
`Category->Window->Colours->Use system color`. That seems to make text at | `Category->Window->Colours->Use system color`. That seems to make text at | ||||
least readable | |||||
least readable | |||||
> I use a custom colour scheme that makes each colour easy to see. | > I use a custom colour scheme that makes each colour easy to see. | ||||
> -HaaTa. | > -HaaTa. |
uint32_t num; | uint32_t num; | ||||
VREF_TRM = 0x60; | VREF_TRM = 0x60; | ||||
VREF_SC = 0xE1; // enable 1.2 volt ref | |||||
VREF_SC = 0xE1; // enable 1.2 volt ref | |||||
if (analog_config_bits == 8) { | if (analog_config_bits == 8) { | ||||
ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); | ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); |
const CLIDictItem scanCLIDict[] = { | const CLIDictItem scanCLIDict[] = { | ||||
#if defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM | #if defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM | ||||
{ "adc", "Read the specified number of values from the ADC at the given pin: <pin> [# of reads]" | { "adc", "Read the specified number of values from the ADC at the given pin: <pin> [# of reads]" | ||||
NL "\t\t See \033[35mLib/pin_map.teensy3\033[0m for ADC0 channel number.", cliFunc_adc }, | |||||
NL "\t\t See \033[35mLib/pin_map.teensy3\033[0m for ADC0 channel number.", cliFunc_adc }, | |||||
{ "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>" | { "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>" | ||||
NL "\t\tADC Resolution -> 8, 10, 12, 16 (bit)" | |||||
NL "\t\t Vref -> 0 (1.2 V), 1 (External)" | |||||
NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit }, | |||||
NL "\t\tADC Resolution -> 8, 10, 12, 16 (bit)" | |||||
NL "\t\t Vref -> 0 (1.2 V), 1 (External)" | |||||
NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit }, | |||||
#endif | #endif | ||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 | #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1 | ||||
{ "dac", "Set DAC output value, from 0 to 4095 (1/4096 Vref to Vref).", cliFunc_dac }, | { "dac", "Set DAC output value, from 0 to 4095 (1/4096 Vref to Vref).", cliFunc_dac }, |
/* Copyright (C) 2011 by Jacob Alexander | /* Copyright (C) 2011 by Jacob Alexander | ||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* in the Software without restriction, including without limitation the rights | * in the Software without restriction, including without limitation the rights | ||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
* copies of the Software, and to permit persons to whom the Software is | * copies of the Software, and to permit persons to whom the Software is | ||||
* furnished to do so, subject to the following conditions: | * furnished to do so, subject to the following conditions: | ||||
* | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
// Just layout the matrix by rows and columns | // Just layout the matrix by rows and columns | ||||
// Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol | // Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol | ||||
// The mode allows for optimization in the kind of scanning algorithms that are done | // The mode allows for optimization in the kind of scanning algorithms that are done | ||||
// | |||||
// | |||||
// The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0). | // The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0). | ||||
// Thus if a row doesn't use all the key positions, you can denote it as 0, which will be ignored/skipped on each scan | // Thus if a row doesn't use all the key positions, you can denote it as 0, which will be ignored/skipped on each scan | ||||
// See the keymap.h file for the various preconfigured arrays. | // See the keymap.h file for the various preconfigured arrays. |
PORTD &= ~D_MASK; | PORTD &= ~D_MASK; | ||||
PORTE &= ~E_MASK; | PORTE &= ~E_MASK; | ||||
DDRB |= (1 << RECOVERY_SINK); // SINK pull | |||||
DDRB |= (1 << RECOVERY_SINK); // SINK pull | |||||
PORTB |= (1 << RECOVERY_CONTROL); | PORTB |= (1 << RECOVERY_CONTROL); | ||||
PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high | PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high | ||||
DDRB |= (1 << RECOVERY_SOURCE); | DDRB |= (1 << RECOVERY_SOURCE); | ||||
PORTB &= ~(1 << RECOVERY_CONTROL); | PORTB &= ~(1 << RECOVERY_CONTROL); | ||||
DDRB &= ~(1 << RECOVERY_SOURCE); | DDRB &= ~(1 << RECOVERY_SOURCE); | ||||
PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low | PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low | ||||
DDRB &= ~(1 << RECOVERY_SINK); // SINK high-imp | |||||
DDRB &= ~(1 << RECOVERY_SINK); // SINK high-imp | |||||
} | } | ||||
} | } | ||||
// Setup the the USART interface for keyboard data input | // Setup the the USART interface for keyboard data input | ||||
// Setup baud rate | // Setup baud rate | ||||
// 16 MHz / ( 16 * Baud ) = UBRR | // 16 MHz / ( 16 * Baud ) = UBRR | ||||
// Baud <- 1200 as per the spec (see datasheet archives), rounding to 1200.1 (as that's as accurate as the timer can be) | // Baud <- 1200 as per the spec (see datasheet archives), rounding to 1200.1 (as that's as accurate as the timer can be) |
inline void Scan_setup() | inline void Scan_setup() | ||||
{ | { | ||||
// Setup the the USART interface for keyboard data input | // Setup the the USART interface for keyboard data input | ||||
// Setup baud rate | // Setup baud rate | ||||
// 16 MHz / ( 16 * Baud ) = UBRR | // 16 MHz / ( 16 * Baud ) = UBRR | ||||
// Baud: 4817 -> 16 MHz / ( 16 * 4817 ) = 207.5981 | // Baud: 4817 -> 16 MHz / ( 16 * 4817 ) = 207.5981 | ||||
} | } | ||||
} | } | ||||
// Send data | |||||
// Send data | |||||
uint8_t Scan_sendData( uint8_t dataPayload ) | uint8_t Scan_sendData( uint8_t dataPayload ) | ||||
{ | { | ||||
// Debug | // Debug |
return 0; | return 0; | ||||
} | } | ||||
// Send data | |||||
// Send data | |||||
uint8_t Scan_sendData( uint8_t dataPayload ) | uint8_t Scan_sendData( uint8_t dataPayload ) | ||||
{ | { | ||||
return 0; | return 0; |
/* Copyright (C) 2011 by Jacob Alexander | /* Copyright (C) 2011 by Jacob Alexander | ||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* in the Software without restriction, including without limitation the rights | * in the Software without restriction, including without limitation the rights | ||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
* copies of the Software, and to permit persons to whom the Software is | * copies of the Software, and to permit persons to whom the Software is | ||||
* furnished to do so, subject to the following conditions: | * furnished to do so, subject to the following conditions: | ||||
* | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
/* Copyright (C) 2012 by Jacob Alexander | /* Copyright (C) 2012 by Jacob Alexander | ||||
* | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* in the Software without restriction, including without limitation the rights | * in the Software without restriction, including without limitation the rights | ||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
* copies of the Software, and to permit persons to whom the Software is | * copies of the Software, and to permit persons to whom the Software is | ||||
* furnished to do so, subject to the following conditions: | * furnished to do so, subject to the following conditions: | ||||
* | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
sei(); // Re-enable Interrupts | sei(); // Re-enable Interrupts | ||||
} | } | ||||
// Send data | |||||
// Send data | |||||
// | // | ||||
// Keyboard Input Guide for Micro Switch 8304 | // Keyboard Input Guide for Micro Switch 8304 | ||||
// 0xBX is for LED F1,F2,Over Type,Lock | // 0xBX is for LED F1,F2,Over Type,Lock |
// Configured as a Pull-up Input - This pin "can" be read as well, it will go to GND when the "Power On" switch is pressed, and will read ~5V otherwise | // Configured as a Pull-up Input - This pin "can" be read as well, it will go to GND when the "Power On" switch is pressed, and will read ~5V otherwise | ||||
// XXX Currently not used by the controller | // XXX Currently not used by the controller | ||||
POWR_DDR &= ~(1 << POWR_POS); | POWR_DDR &= ~(1 << POWR_POS); | ||||
POWR_PORT |= (1 << POWR_POS); | |||||
POWR_PORT |= (1 << POWR_POS); | |||||
// Reset the keyboard before scanning, we might be in a wierd state | // Reset the keyboard before scanning, we might be in a wierd state | ||||
scan_resetKeyboard(); | scan_resetKeyboard(); |
// ----- Macros ----- | // ----- Macros ----- | ||||
// -- pinSetup Macros -- | // -- pinSetup Macros -- | ||||
#define REG_SET(reg) reg |= (1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) // Modulo 10 for the define offset for each pin set 12 or 32 -> shift of 2 | |||||
#define REG_SET(reg) reg |= (1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) // Modulo 10 for the define offset for each pin set 12 or 32 -> shift of 2 | |||||
#define REG_UNSET(reg) reg &= ~(1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) | #define REG_UNSET(reg) reg &= ~(1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) | ||||
#define PIN_SET(pin,scan,direction) \ | #define PIN_SET(pin,scan,direction) \ | ||||
case scanDual: \ | case scanDual: \ | ||||
REG_SET(port##pin); break; \ | REG_SET(port##pin); break; \ | ||||
case scanCol_powrRow: REG_UNSET(ddr##pin); REG_UNSET(DDR##pin); \ | case scanCol_powrRow: REG_UNSET(ddr##pin); REG_UNSET(DDR##pin); \ | ||||
REG_SET(port##pin); REG_SET(PORT##pin); break; \ | |||||
REG_SET(port##pin); REG_SET(PORT##pin); break; \ | |||||
case powrRow: break; \ | case powrRow: break; \ | ||||
case powrCol: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | case powrCol: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | ||||
REG_SET(port##pin); REG_SET(PORT##pin); break; \ | REG_SET(port##pin); REG_SET(PORT##pin); break; \ | ||||
case scanDual: \ | case scanDual: \ | ||||
REG_SET(port##pin); break; \ | REG_SET(port##pin); break; \ | ||||
case scanCol_powrRow: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | case scanCol_powrRow: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | ||||
REG_UNSET(port##pin); REG_UNSET(PORT##pin); break; \ | |||||
REG_UNSET(port##pin); REG_UNSET(PORT##pin); break; \ | |||||
case powrRow: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | case powrRow: REG_SET(ddr##pin); REG_SET(DDR##pin); \ | ||||
REG_SET(port##pin); REG_SET(PORT##pin); break; \ | |||||
REG_SET(port##pin); REG_SET(PORT##pin); break; \ | |||||
case powrCol: break; \ | case powrCol: break; \ | ||||
} \ | } \ | ||||
break | break | ||||
if ( showDebug == 0 ) // Only show once | if ( showDebug == 0 ) // Only show once | ||||
{ | { | ||||
matrix_debugPins(); | matrix_debugPins(); | ||||
} | |||||
} | |||||
} | } | ||||
// Scans the given matrix determined by the scanMode method | // Scans the given matrix determined by the scanMode method | ||||
_delay_us( 1 ); | _delay_us( 1 ); | ||||
col = 1; | col = 1; | ||||
row = 1; | row = 1; | ||||
for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ ) | |||||
for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ ) | |||||
{ | { | ||||
// Scan over the pins for each of the rows, and using the pin alias to determine which pin to set | // Scan over the pins for each of the rows, and using the pin alias to determine which pin to set | ||||
// (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.)) | // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.)) | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) | // NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) | ||||
// Other Bits: Pressed state sample counter | // Other Bits: Pressed state sample counter | ||||
extern uint8_t KeyIndex_Array [KEYBOARD_KEYS + 1]; | extern uint8_t KeyIndex_Array [KEYBOARD_KEYS + 1]; | ||||
static const uint8_t KeyIndex_Size = KEYBOARD_KEYS; | |||||
static const uint8_t KeyIndex_Size = KEYBOARD_KEYS; | |||||
extern volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER]; | extern volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER]; | ||||
extern volatile uint8_t KeyIndex_BufferUsed; | extern volatile uint8_t KeyIndex_BufferUsed; |
#!/bin/bash | #!/bin/bash | ||||
###| Builder Script |### | ###| Builder Script |### | ||||
# | |||||
# | |||||
# Builds all permutations of modules | # Builds all permutations of modules | ||||
# This script is an attempt to maintain module sanity as new ones are added | # This script is an attempt to maintain module sanity as new ones are added | ||||
# | # |