vxkernel - v0.7.0-5 : setup libSSP (WIP) + support USB description step (WIP)
*add* > [cpu] | add SH-CPU context structure | try to support Stack-Protector but seems not insert check during compile-time | add stack abord routine invocation (WIP) > [usb] | add configuration structure | add configuration handling | add USB logger (WIP) | add USB high-level abstraction for debugging (WIP) | add USB driver | add fake SDL2 USB driver *update* > [usb] | clean DCP configuration API (WIP) | prepare proper pipe handling (WIP) | isolate USB protocole initialisation | enable some interruption > [vxsdk.toml] | force enable libSSP (but seems not work o(x_x)o) *fix* > [usb] | fix endpoint type ID > [display] | [dtext] workaround to possible stack corruption (WIP) > [hypervisor] | [switch] fix NULL power primitives > [vxdev] | use `/usr/bin/env python3` instead of `python3`
This commit is contained in:
parent
c6aa4b5ac4
commit
18e895dfb7
|
@ -6,32 +6,35 @@
|
|||
# define __VHEX_DEFS_ATTRIBUTES__
|
||||
|
||||
/* Objects from specific sections */
|
||||
#define VSECTION(x) __attribute__((section(x)))
|
||||
#define VSECTION(x) __attribute__((section(x)))
|
||||
|
||||
/* Disable Stack Protector */
|
||||
#define VNO_STACK_PROTECTOR __attribute__((no_stack_protector))
|
||||
|
||||
/* Unused parameters or variables */
|
||||
#define VUNUSED __attribute__((unused))
|
||||
#define VUNUSED __attribute__((unused))
|
||||
/* Functions that *must* be inlined */
|
||||
#define VINLINE __attribute__((always_inline)) inline
|
||||
#define VINLINE __attribute__((always_inline)) inline
|
||||
|
||||
/* Aligned variables */
|
||||
#define VALIGNED(x) __attribute__((aligned(x)))
|
||||
#define VALIGNED(x) __attribute__((aligned(x)))
|
||||
/* Packed structures. I require explicit alignment because if it's unspecified,
|
||||
GCC cannot optimize access size, and reads to memory-mapped I/O with invalid
|
||||
access sizes silently fail - honestly you don't want this to happen */
|
||||
#define VPACKED(x) __attribute__((packed, aligned(x)))
|
||||
#define VPACKED(x) __attribute__((packed, aligned(x)))
|
||||
/* Packed enumerations */
|
||||
#define VPACKED_ALONE __attribute__((packed))
|
||||
#define VPACKED_ALONE __attribute__((packed))
|
||||
/* Transparent unions */
|
||||
#define VTRANSPARENT __attribute__((transparent_union))
|
||||
#define VTRANSPARENT __attribute__((transparent_union))
|
||||
|
||||
/* Weak symbols */
|
||||
#define VWEAK __attribute__((weak))
|
||||
#define VWEAK __attribute__((weak))
|
||||
|
||||
/* Constructors */
|
||||
#define VCONSTRUCTOR __attribute__((constructor))
|
||||
#define VDESTRUCTOR __attribute__((destructor))
|
||||
#define VCONSTRUCTOR __attribute__((constructor))
|
||||
#define VDESTRUCTOR __attribute__((destructor))
|
||||
|
||||
/* Functions that do not return */
|
||||
#define VNORETURN __attribute__((noreturn))
|
||||
#define VNORETURN __attribute__((noreturn))
|
||||
|
||||
#endif /*__VHEX_DEFS_ATTRIBUTES__*/
|
||||
|
|
|
@ -4,6 +4,21 @@
|
|||
#include <vhex/defs/types.h>
|
||||
#include <vhex/defs/attributes.h>
|
||||
|
||||
//---
|
||||
// Complet CPU contexte
|
||||
//---
|
||||
|
||||
struct sh7305_cpu_ctx {
|
||||
uintptr_t pr;
|
||||
uintptr_t spc;
|
||||
uintptr_t ssr;
|
||||
uintptr_t mach;
|
||||
uintptr_t macl;
|
||||
uintptr_t gbr;
|
||||
uintptr_t sgr;
|
||||
uintptr_t r[16];
|
||||
};
|
||||
|
||||
//---
|
||||
// Access to CPU registers
|
||||
//---
|
||||
|
|
|
@ -468,20 +468,28 @@ extern void sh7305_usb_interrupt_handler(void);
|
|||
/* sh7305_usb_request_handle() : handle USB request */
|
||||
extern void sh7305_usb_request_handle(void);
|
||||
|
||||
#include <vhex/usb/device.h>
|
||||
#include <vhex/usb/configuration.h>
|
||||
|
||||
/* sh7305_usb_open() : power on the module and setup USB module */
|
||||
extern int sh7305_usb_open(struct usb_full_device *device);
|
||||
|
||||
/* sh7305_configuration_resolve() : check and resolve USB configuration */
|
||||
extern int sh7305_usb_configuration_resolve(struct usb_full_device *device);
|
||||
|
||||
|
||||
/* sh7305_pipe_find() : try to find a pipe */
|
||||
extern int sh7305_usb_pipe_find(int type);
|
||||
|
||||
|
||||
|
||||
/* sh7305_usb_dcp_prepare() : prepare FIFO buffer */
|
||||
extern void sh7305_usb_dcp_prepare(void);
|
||||
|
||||
/* sh7305_usb_dcp_write() : send data through DCP pipe */
|
||||
extern int sh7305_usb_dcp_write(void *buffer, size_t n);
|
||||
|
||||
/* sh7305_usb_dcp_commit() : send data */
|
||||
extern void sh7305_usb_dcp_commit(void);
|
||||
|
||||
|
||||
//---
|
||||
// Utils
|
||||
//---
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
#include <vhex/usb/logger.h>
|
||||
#include <vhex/usb/primitives.h>
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef __VHEX_USB_CONFIGURATION_H__
|
||||
#define __VHEX_USB_CONFIGURATION_H__ 1
|
||||
|
||||
#include <vhex/usb/descriptor.h>
|
||||
|
||||
/* usb_full_interface - interface descriptor, names, and endpoints */
|
||||
struct usb_full_interface {
|
||||
usb_dc_interf_t *descriptor;
|
||||
char **strs;
|
||||
usb_dc_endpnt_t **endpoint;
|
||||
};
|
||||
|
||||
/* usb_full_config - interface descriptor, names, and interfaces */
|
||||
struct usb_full_config {
|
||||
usb_dc_config_t *descriptor;
|
||||
char **strs;
|
||||
struct usb_full_interface **interface;
|
||||
};
|
||||
|
||||
/* usb_full_device - interface descriptor, names, and configurations */
|
||||
struct usb_full_device {
|
||||
usb_dc_device_t *descriptor;
|
||||
char **strs;
|
||||
struct usb_full_config **config;
|
||||
};
|
||||
|
||||
/* __USB_MAX_* - internal configuration limit */
|
||||
#define __USB_MAX_DC_CONF 2
|
||||
#define __USB_MAX_DC_INTR 4
|
||||
#define __USB_MAX_DC_ENDP 9
|
||||
|
||||
/* usb_config_resolve() : check and resolve USB configuration */
|
||||
extern int usb_config_resolve(struct usb_full_device *device);
|
||||
|
||||
/* usb_config_select_config() : try to selecte a configuration */
|
||||
extern int usb_config_select_config(int idx);
|
||||
|
||||
/* usb_config_get_dc_device() : get device descriptor */
|
||||
extern int usb_config_get_dc_device(usb_dc_device_t **dc_device, int idx);
|
||||
|
||||
/* usb_config_get_dc_config() : get config descriptor */
|
||||
extern int usb_config_get_dc_config(
|
||||
usb_dc_config_t **dc_config,
|
||||
int idx,
|
||||
int *isidx,
|
||||
int *ieidx
|
||||
);
|
||||
|
||||
/* usb_config_get_dc_interf() : get interface descriptor */
|
||||
extern int usb_config_get_dc_interf(
|
||||
usb_dc_interf_t **dc_interf,
|
||||
int idx,
|
||||
int *esidx,
|
||||
int *eeidx
|
||||
);
|
||||
|
||||
/* usb_config_get_dc_endpoint() : get endpoint descriptor */
|
||||
extern int usb_config_get_dc_endpnt(usb_dc_endpnt_t **dc_endpoint, int idx);
|
||||
|
||||
#endif /* __VHEX_USB_CONFIGURATION_H__ */
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef __VHEX_USB_DESCRIPTOR_H__
|
||||
#define __VHEX_USB_DESCRIPTOR_H__ 1
|
||||
|
||||
#include <vhex/usb/descriptor/device.h>
|
||||
#include <vhex/usb/descriptor/configuration.h>
|
||||
#include <vhex/usb/descriptor/interface.h>
|
||||
#include <vhex/usb/descriptor/endpoint.h>
|
||||
|
||||
/* usb_dc_* - create kernel aliases */
|
||||
typedef struct usb_descriptor_device usb_dc_device_t;
|
||||
typedef struct usb_descriptor_configuration usb_dc_config_t;
|
||||
typedef struct usb_descriptor_interface usb_dc_interf_t;
|
||||
typedef struct usb_descriptor_endpoint usb_dc_endpnt_t;
|
||||
|
||||
#endif /* __VHEX_USB_DESCRIPTOR_H__ */
|
|
@ -30,8 +30,11 @@ struct usb_descriptor_configuration {
|
|||
uint8_t bMaxPower;
|
||||
} VPACKED_ALONE;
|
||||
|
||||
//---
|
||||
// Helpers
|
||||
//---
|
||||
|
||||
#include <vhex/usb/descriptor/types.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
|
||||
/* USB_DECLARE_DESC_CONF - helper to declare configuration descriptor */
|
||||
#define USB_DECLARE_DESC_CONF(name, ...) \
|
||||
|
|
|
@ -14,15 +14,18 @@ struct usb_descriptor_device {
|
|||
uint8_t bMaxPacketSize0; /* packet size of endpoint 0 */
|
||||
uint16_t idVendor; /* vendor ID (assigned by USB-IF) */
|
||||
uint16_t idProduct; /* product ID (assigned by manufacturer) */
|
||||
uint16_t bcdDevice; /* device release version (0x220 -> 2.220) */
|
||||
uint16_t bcdDevice; /* device release version (0x220 -> 2.20) */
|
||||
uint8_t iManufacturer; /* index of string descr. for Manufacturer */
|
||||
uint8_t iProduct; /* index of string descr. for product */
|
||||
uint8_t iSerialNumber; /* index of string descr. for serial number */
|
||||
uint8_t bNumConfigurations;/* number of possible configuration */
|
||||
} VPACKED_ALONE;
|
||||
|
||||
//---
|
||||
// helpers
|
||||
//---
|
||||
|
||||
#include <vhex/usb/descriptor/types.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
|
||||
/* USB_DECLARE_DESC_DEV - helper to declare device descriptor */
|
||||
#define USB_DECLARE_DESC_DEVICE(name, ...) \
|
||||
|
@ -34,7 +37,6 @@ struct usb_descriptor_device {
|
|||
{ \
|
||||
.bLengh = sizeof(struct usb_descriptor_device), \
|
||||
.bDescriptorType = USB_DESCRIPTOR_DEVICE, \
|
||||
.bcdUSB = USB_WORD_TO(0x200), \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,11 @@ struct usb_descriptor_endpoint {
|
|||
uint8_t bInterval; /* Interval for polling endpoint */
|
||||
} VPACKED_ALONE;
|
||||
|
||||
//---
|
||||
// Helpers
|
||||
//---
|
||||
|
||||
#include <vhex/usb/descriptor/types.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
|
||||
/* USB_DECLARE_DESC_ENDPOINT - helper to declare endpoint descriptor */
|
||||
#define USB_DECLARE_DESC_ENDPOINT(name, ...) \
|
||||
|
|
|
@ -16,8 +16,11 @@ struct usb_descriptor_interface {
|
|||
uint8_t iInterface; /* index of string desc. for this interface */
|
||||
} VPACKED_ALONE;
|
||||
|
||||
//---
|
||||
// Helpers
|
||||
//---
|
||||
|
||||
#include <vhex/usb/descriptor/types.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
|
||||
/* USB_DECLARE_DESC_INTERFACE - helper to declare interface descriptor */
|
||||
#define USB_DECLARE_DESC_INTERFACE(name, ...) \
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
#define USB_DESCRIPTOR_DEVICE 1
|
||||
#define USB_DESCRIPTOR_CONFIGURATION 2
|
||||
#define USB_DESCRIPTOR_INTERFACE 4
|
||||
#define USB_DESCRIPTOR_ENDPOINT 7
|
||||
#define USB_DESCRIPTOR_ENDPOINT 5
|
||||
|
||||
#endif /* __VHEX_USB_DESCRIPTOR_TYPES_H__ */
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef __VHEX_USB_DEVICE_H__
|
||||
#define __VHEX_USB_DEVICE_H__ 1
|
||||
|
||||
#include <vhex/defs/types.h>
|
||||
#include <vhex/usb/descriptor/device.h>
|
||||
#include <vhex/usb/descriptor/configuration.h>
|
||||
#include <vhex/usb/descriptor/interface.h>
|
||||
#include <vhex/usb/descriptor/endpoint.h>
|
||||
|
||||
struct usb_full_interface {
|
||||
struct usb_descriptor_interface *descriptor;
|
||||
char **strs;
|
||||
struct usb_descriptor_endpoint **endpoint;
|
||||
};
|
||||
|
||||
struct usb_full_config {
|
||||
struct usb_descriptor_configuration *descriptor;
|
||||
char **strs;
|
||||
struct usb_full_interface **interface;
|
||||
};
|
||||
|
||||
struct usb_full_device {
|
||||
struct usb_descriptor_device *descriptor;
|
||||
char **strs;
|
||||
struct usb_full_config **config;
|
||||
};
|
||||
|
||||
#endif /* __VHEX_USB_DEVICE_H__ */
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __VHEX_USB_INFO_H__
|
||||
#define __VHEX_USB_INFO_H__ 1
|
||||
|
||||
#include <vhex/usb/interface.h>
|
||||
#include <vhex/usb/logger.h>
|
||||
|
||||
/* internal USB module information */
|
||||
struct usb_mod_info
|
||||
{
|
||||
struct usb_drv_interface driver;
|
||||
struct {
|
||||
bool attached;
|
||||
usb_logger_t device;
|
||||
} logger;
|
||||
};
|
||||
|
||||
/* internaly used by the module */
|
||||
extern struct usb_mod_info usb_mod_info;
|
||||
|
||||
#endif /* __VHEX_USB_INFO_H__ */
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef __VHEX_USB_INTERFACE_H__
|
||||
#define __VHEX_USB_INTERFACE_H__ 1
|
||||
|
||||
#include <vhex/usb/configuration.h>
|
||||
|
||||
struct usb_drv_interface
|
||||
{
|
||||
/* "classic" primitives API */
|
||||
int (*open)(struct usb_full_device *device);
|
||||
|
||||
/* pipe API */
|
||||
int (*pipe_find)(int type);
|
||||
};
|
||||
|
||||
#endif /* __VHEX_USB_INTERFACE_H__ */
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __VHEX_USB_PIPE_H__
|
||||
#define __VHEX_USB_PIPE_H__ 1
|
||||
|
||||
/* usb_pipe_find() - try to find a free pipe of type `type` (BULK, ...) */
|
||||
extern int usb_pipe_find(int type);
|
||||
|
||||
#endif /* __VHEX_USB_PIPE_H__ */
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef __VHEX_USB_PRIMITIVES_H__
|
||||
#define __VHEX_USB_PRIMITIVES_H__ 1
|
||||
|
||||
#include <vhex/usb/configuration.h>
|
||||
|
||||
/* usb_open() : open primitive */
|
||||
extern int usb_open(struct usb_full_device *device);
|
||||
|
||||
#endif /* __VHEX_USB_PRIMITIVES_H__ */
|
|
@ -0,0 +1,37 @@
|
|||
#include <vhex/usb/interface.h>
|
||||
#include <vhex/driver.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static int sdl2_usb_open(void)
|
||||
{
|
||||
printf("SDL2 : USB driver not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sdl2_usb_pipe_find(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* declare driver */
|
||||
struct vhex_driver drv_usb = {
|
||||
.name = "USB",
|
||||
.hpowered = NULL,
|
||||
.hpoweron = NULL,
|
||||
.hpoweroff = NULL,
|
||||
.hsave = NULL,
|
||||
.hrestore = NULL,
|
||||
.configure = NULL,
|
||||
.state_size = 4,
|
||||
.flags = {
|
||||
.USB = 1,
|
||||
.SHARED = 0,
|
||||
.UNUSED = 1,
|
||||
},
|
||||
.module_data = &(struct usb_drv_interface){
|
||||
.open = (void*)&sdl2_usb_open,
|
||||
.pipe_find = (void*)&sdl2_usb_pipe_find
|
||||
}
|
||||
};
|
||||
VHEX_DECLARE_DRIVER(06, drv_usb);
|
|
@ -0,0 +1,52 @@
|
|||
.text
|
||||
.global ___stack_chk_guard
|
||||
.global ___stack_chk_fail
|
||||
|
||||
|
||||
.balign 4
|
||||
|
||||
___stack_chk_guard:
|
||||
.long 0xdeb0cad0
|
||||
|
||||
.balign 4
|
||||
|
||||
___stack_chk_fail:
|
||||
! Generate "CPU" context
|
||||
sts.l pr, @-r15
|
||||
stc.l spc, @-r15
|
||||
stc.l ssr, @-r15
|
||||
sts.l mach, @-r15
|
||||
sts.l macl, @-r15
|
||||
stc.l gbr, @-r15
|
||||
stc.l sgr, @-r15
|
||||
mov.l r14, @-r15
|
||||
mov.l r13, @-r15
|
||||
mov.l r12, @-r15
|
||||
mov.l r11, @-r15
|
||||
mov.l r10, @-r15
|
||||
mov.l r9, @-r15
|
||||
mov.l r8, @-r15
|
||||
mov.l r7, @-r15
|
||||
mov.l r6, @-r15
|
||||
mov.l r5, @-r15
|
||||
mov.l r4, @-r15
|
||||
mov.l r3, @-r15
|
||||
mov.l r2, @-r15
|
||||
mov.l r1, @-r15
|
||||
mov.l r0, @-r15
|
||||
|
||||
! invoke the panic handler, it SHOULD never return
|
||||
mov.l sh7305_cpu_stack_chk_fail, r0
|
||||
jsr @r0
|
||||
mov r15, r4
|
||||
|
||||
! handle panic handler error
|
||||
panic_handler_error:
|
||||
bra panic_handler_error
|
||||
nop
|
||||
|
||||
|
||||
.balign 4
|
||||
|
||||
sh7305_cpu_stack_chk_fail:
|
||||
.long _sh7305_cpu_stack_chk_fail
|
|
@ -0,0 +1,27 @@
|
|||
#include <vhex/defs/attributes.h>
|
||||
#include <vhex/driver/mpu/sh/sh7305/cpu.h>
|
||||
#include <vhex/display.h>
|
||||
|
||||
|
||||
/* defined by the linker script */
|
||||
extern uint32_t __kernel_reloc_start;
|
||||
|
||||
/* sh7305_cpu_stack_chk_fail() : stack smashing error */
|
||||
VNO_STACK_PROTECTOR
|
||||
void sh7305_cpu_stack_chk_fail(struct sh7305_cpu_ctx *ctx)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
dtext(6, 3, C_BLACK, "Stack smashing detected (System ERROR)");
|
||||
|
||||
dtext( 6, 45, C_BLACK, "PC");
|
||||
dprint(38, 45, C_BLACK, "= %08x", ctx->pr - (uintptr_t)&__kernel_reloc_start);
|
||||
dtext(261, 45, C_BLACK, "(Error location)");
|
||||
|
||||
dprint( 6, 90, C_BLACK, "reloc base = %p", &__kernel_reloc_start);
|
||||
|
||||
dtext(6, 120, C_BLACK, "An unrecoverable error occurred in the add-in.");
|
||||
dtext(6, 135, C_BLACK, "Please press the RESET button to restart the");
|
||||
dtext(6, 150, C_BLACK, "calculator.");
|
||||
dupdate();
|
||||
while (1) { __asm__ volatile ("sleep"); }
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
#include <vhex/display.h>
|
||||
#include <vhex/defs/types.h>
|
||||
|
||||
/* defined by the linker script */
|
||||
extern uint32_t __kernel_reloc_start;
|
||||
|
||||
void sh7305_intc_exch_panic(void)
|
||||
{
|
||||
extern uint32_t __kernel_reloc_start;
|
||||
uint32_t PC;
|
||||
uint32_t TEA;
|
||||
uint32_t TRA;
|
||||
|
@ -14,7 +16,7 @@ void sh7305_intc_exch_panic(void)
|
|||
|
||||
TEA = *(volatile uint32_t *)0xff00000c;
|
||||
TRA = *(volatile uint32_t *)0xff000020 >> 2;
|
||||
code = *(volatile uint32_t*)0xff000024;
|
||||
code = *(volatile uint32_t *)0xff000024;
|
||||
|
||||
dclear(C_WHITE);
|
||||
dtext(6, 3, C_BLACK, "An exception occured! (System ERROR)");
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
#include <vhex/driver/mpu/sh/sh7305/usb.h>
|
||||
#include <vhex/driver/cpu.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//---
|
||||
// Internals
|
||||
//---
|
||||
|
||||
/* abitrary USB configuration limit (TODO : update me?) */
|
||||
#define __SH7305_USB_MAX_DC_CONF 2
|
||||
#define __SH7305_USB_MAX_DC_INTR 4
|
||||
#define __SH7305_USB_MAX_DC_ENDP 9
|
||||
|
||||
/* internal copy of each descriptor (TODO : update me?) */
|
||||
struct usb_descriptor_device __sh7305_usb_dc_device;
|
||||
struct usb_descriptor_configuration __sh7305_usb_dc_conf[__SH7305_USB_MAX_DC_CONF];
|
||||
struct usb_descriptor_interface __sh7305_usb_dc_interf[__SH7305_USB_MAX_DC_INTR];
|
||||
struct usb_descriptor_endpoint __sh7305_usb_dc_endpoint[__SH7305_USB_MAX_DC_ENDP];
|
||||
|
||||
/* sh7305_conf_check_conf() : check and patch interface desc. */
|
||||
static int sh7305_conf_check_endpoint(
|
||||
struct usb_descriptor_endpoint **endpoint,
|
||||
size_t *total
|
||||
) {
|
||||
int pipe_id;
|
||||
int i;
|
||||
|
||||
if (endpoint == NULL)
|
||||
return -3;
|
||||
for (i = 0 ; endpoint[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __SH7305_USB_MAX_DC_ENDP) {
|
||||
usb_logger_write("- too many endpoint (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
*total += sizeof(struct usb_descriptor_endpoint);
|
||||
pipe_id = sh7305_usb_pipe_find(endpoint[i]->bmAttributes.trans);
|
||||
if (pipe_id < 0)
|
||||
return pipe_id;
|
||||
endpoint[i]->bEndpointAddress.number = pipe_id;
|
||||
memcpy(
|
||||
&__sh7305_usb_dc_endpoint[i],
|
||||
endpoint[i],
|
||||
sizeof(struct usb_descriptor_endpoint)
|
||||
);
|
||||
usb_logger_write("- use pipe %d\n", pipe_id);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* sh7305_conf_check_conf() : check and patch interface desc. */
|
||||
static int sh7305_conf_check_interface(
|
||||
struct usb_full_interface **interface,
|
||||
size_t *total
|
||||
) {
|
||||
int nbendpoint;
|
||||
int i;
|
||||
|
||||
if (interface == NULL)
|
||||
return -3;
|
||||
for (i = 0 ; interface[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __SH7305_USB_MAX_DC_INTR) {
|
||||
usb_logger_write("- too many interface (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
//FIXME : check strings
|
||||
*total += sizeof(struct usb_descriptor_interface);
|
||||
nbendpoint = sh7305_conf_check_endpoint(interface[i]->endpoint, total);
|
||||
if (nbendpoint < 0)
|
||||
return nbendpoint;
|
||||
interface[i]->descriptor->bInterfaceNumber = i + 1;
|
||||
interface[i]->descriptor->bNumEndpoints = nbendpoint;
|
||||
memcpy(
|
||||
&__sh7305_usb_dc_interf[i],
|
||||
interface[i],
|
||||
sizeof(struct usb_descriptor_interface)
|
||||
);
|
||||
usb_logger_write("- use interface %d\n", i + 1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* sh7305_conf_check_conf() : check and patch configuration desc. */
|
||||
static int sh7305_conf_check_conf(struct usb_full_config **config)
|
||||
{
|
||||
int nbinterf;
|
||||
size_t total;
|
||||
int i;
|
||||
|
||||
if (config == NULL)
|
||||
return -2;
|
||||
for (i = 0 ; config[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __SH7305_USB_MAX_DC_CONF) {
|
||||
usb_logger_write("- too many configuration (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
//FIXME : check strings
|
||||
total = sizeof(struct usb_descriptor_configuration);
|
||||
nbinterf = sh7305_conf_check_interface(config[i]->interface, &total);
|
||||
if (nbinterf < 0)
|
||||
return nbinterf;
|
||||
config[i]->descriptor->wTotalLengh = total;
|
||||
config[i]->descriptor->bNumInterfaces = nbinterf;
|
||||
config[i]->descriptor->bConfigurationValue = i + 1;
|
||||
memcpy(
|
||||
&__sh7305_usb_dc_conf[i],
|
||||
config[i],
|
||||
sizeof(struct usb_descriptor_configuration)
|
||||
);
|
||||
usb_logger_write("- use configuration %d\n", i + 1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* sh7305_usb_configuration_resolve() : check and resolve USB configuration */
|
||||
int sh7305_usb_configuration_resolve(struct usb_full_device *device)
|
||||
{
|
||||
int nbconf;
|
||||
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
|
||||
//FIXME : check string validity
|
||||
|
||||
cpu_atomic_start();
|
||||
|
||||
/* patch configuration descriptors */
|
||||
nbconf = sh7305_conf_check_conf(device->config);
|
||||
if (nbconf < 0)
|
||||
return nbconf;
|
||||
|
||||
/* patch device descriptor */
|
||||
device->descriptor->bNumConfigurations = nbconf;
|
||||
memcpy(
|
||||
&__sh7305_usb_dc_device,
|
||||
device->descriptor,
|
||||
sizeof(struct usb_descriptor_device)
|
||||
);
|
||||
|
||||
cpu_atomic_end();
|
||||
return 0;
|
||||
}
|
|
@ -3,34 +3,55 @@
|
|||
/* sh7305_usb_dcp_write() : send data through DCP pipe */
|
||||
int sh7305_usb_dcp_write(void *buffer, size_t n)
|
||||
{
|
||||
//FIXME : common interface with other pipe
|
||||
//FIXME : check buffer size (block send)
|
||||
//
|
||||
/* force kevin */
|
||||
SH7305_USB_INTSTS0_CLEAR(VALID);
|
||||
|
||||
/* setup to write mode */
|
||||
SH7305_USB.CFIFOSEL.ISEL = 1;
|
||||
SH7305_USB.CFIFOSEL.CURPIPE = 0;
|
||||
SH7305_USB.CFIFOSEL.BIGEND = 1;
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL == 0);
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.DCPCTR.BSTS == 0);
|
||||
|
||||
/* send data */
|
||||
SH7305_USB.DCPCTR.PID = 1;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
*((volatile uint8_t*)&SH7305_USB.CFIFO) = ((uint8_t*)buffer)[i];
|
||||
}
|
||||
|
||||
/* commit transfert */
|
||||
SH7305_USB.CFIFOCTR.BVAL = 1;
|
||||
SH7305_USB.DCPCTR.CCPL = 1;
|
||||
|
||||
usb_logger_write(
|
||||
"DCPCTR=%04X-CFIFOSEL=%04X-INTSTS=%04X\n"
|
||||
"buffer = %d\n",
|
||||
SH7305_USB.DCPCTR.word, SH7305_USB.CFIFOSEL.word, SH7305_USB.INTSTS0.word,
|
||||
n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* sh7305_usb_dcp_prepare() : prepare FIFO buffer */
|
||||
void sh7305_usb_dcp_prepare(void)
|
||||
{
|
||||
/* Configure Control FIFO pipe.
|
||||
* @config
|
||||
* - RCNT =1 the CFIFOCTR.DTLN is decremented only during reading
|
||||
* - REW =0 buffer pointer is not rewound
|
||||
* - MBW =0b00 select 8bits access
|
||||
* - BIGEND =1 use big endian
|
||||
* - ISEL =1 select writting pipe
|
||||
* - CURPIPE =0b0000 select DCP pipe
|
||||
* @notes
|
||||
* - as the SH7724 documentation explain at section 31.4.8, we cannot
|
||||
* change the bits access during reading or writing once setuped. So, we
|
||||
* use 8-bits writing to avoid buffer alignement fault during
|
||||
* configuration transaction. */
|
||||
SH7305_USB.CFIFOSEL.RCNT = 1;
|
||||
SH7305_USB.CFIFOSEL.REW = 0;
|
||||
SH7305_USB.CFIFOSEL.MBW = 0b00;
|
||||
SH7305_USB.CFIFOSEL.BIGEND = 1;
|
||||
SH7305_USB.CFIFOSEL.CURPIPE = 0b0000;
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.CURPIPE != 0b0000);
|
||||
SH7305_USB.CFIFOSEL.ISEL = 1;
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL == 0);
|
||||
|
||||
/* wait until the CDP buffer is available */
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.DCPCTR.BSTS == 0);
|
||||
|
||||
/* send data */
|
||||
SH7305_USB.DCPCTR.PID = 1;
|
||||
}
|
||||
|
||||
/* sh7305_usb_dcp_commit() : send data */
|
||||
void sh7305_usb_dcp_commit(void)
|
||||
{
|
||||
/* wait buffer sync. and indicate that the writing has beens finished /
|
||||
* @notes
|
||||
* - SH7724 section 31.4.8 */
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOCTR.FRDY == 0);
|
||||
SH7305_USB.CFIFOCTR.BVAL = 1;
|
||||
|
||||
/* finish the control transfert stage
|
||||
* @notes
|
||||
* - SH7724 section 31.4.29 */
|
||||
SH7305_USB.DCPCTR.CCPL = 1;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <vhex/driver/mpu/sh/sh7305/usb.h>
|
||||
#include <vhex/driver/mpu/sh/sh7305/intc.h>
|
||||
#include <vhex/usb/configuration.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
//---
|
||||
|
@ -15,7 +16,7 @@ int sh7305_usb_open(struct usb_full_device *device)
|
|||
|
||||
/* check and update device configuration */
|
||||
usb_logger_write("Configuration check...\n");
|
||||
ret = sh7305_usb_configuration_resolve(device);
|
||||
ret = usb_config_resolve(device);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
|
@ -62,23 +63,6 @@ int sh7305_usb_open(struct usb_full_device *device)
|
|||
SH7305_USB.SOFCFG.BRDYM = 0;
|
||||
SH7305_USB.SOFCFG.HIGH = 1;
|
||||
|
||||
/* Configure Control FIFO pipe.
|
||||
* @notes
|
||||
* - RCNT =1 the CFIFOCTR.DTLN is decremented only during reading
|
||||
* - REW =0 buffer pointer is not rewound
|
||||
* - MBW =0b00 select 8bits access
|
||||
* - BIGEND =1 use big endian
|
||||
* - ISEL =0 select reading pipe
|
||||
* - CURPIPE =0b0000 select DCP pipe */
|
||||
SH7305_USB.CFIFOSEL.RCNT = 1;
|
||||
SH7305_USB.CFIFOSEL.REW = 0;
|
||||
SH7305_USB.CFIFOSEL.MBW = 0b00;
|
||||
SH7305_USB.CFIFOSEL.BIGEND = 1;
|
||||
SH7305_USB.CFIFOSEL.CURPIPE = 0b0000;
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.CURPIPE != 0b0000);
|
||||
SH7305_USB.CFIFOSEL.ISEL = 0;
|
||||
SH7305_USB_REG_SYNC(SH7305_USB.CFIFOSEL.ISEL != 0);
|
||||
|
||||
/* Pipes configuration */
|
||||
usb_logger_write("USB pipes configuration...\n");
|
||||
|
||||
|
@ -98,8 +82,8 @@ int sh7305_usb_open(struct usb_full_device *device)
|
|||
* - VBSE =1 enable VBUS interruption
|
||||
* - RSME =0 disable Resume interruption
|
||||
* - SOFE =0 disable Frame Number Update interruption
|
||||
* - DVSE =0 enable Device State Transition
|
||||
* - CTRE =0 disable Control Transfert Stage Transition
|
||||
* - DVSE =1 enable Device State Transition
|
||||
* - CTRE =1 enable Control Transfert Stage Transition
|
||||
* - BEMPE =0 disable Buffer Empty interrupt
|
||||
* - NRDYE =0 disable Buffer Not Ready interrupt
|
||||
* - BRDYE =0 disable Buffer Ready interrupt */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <vhex/driver/mpu/sh/sh7305/usb.h>
|
||||
#include <vhex/usb/configuration.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
#include <vhex/display.h>
|
||||
#include <vhex/usb.h>
|
||||
|
@ -9,12 +10,6 @@
|
|||
// Internal error API
|
||||
//---
|
||||
|
||||
/* defined in <configuration.c> */
|
||||
extern struct usb_descriptor_device __sh7305_usb_dc_device;
|
||||
extern struct usb_descriptor_configuration *__sh7305_usb_dc_conf;
|
||||
extern struct usb_descriptor_interface *__sh7305_usb_dc_interf;
|
||||
extern struct usb_descriptor_endpoint *__sh7305_usb_dc_endpoint;
|
||||
|
||||
/* sh7305_usb_request_unimplemented() : not implemented request */
|
||||
static void sh7305_usb_request_unimplemented(
|
||||
char const * const name,
|
||||
|
@ -42,8 +37,19 @@ static void sh7305_usb_request_error(char const * const text, ...)
|
|||
}
|
||||
|
||||
/* sh7305_usb_request_get_descriptor() : send descriptor through DCP */
|
||||
static void sh7305_usb_request_get_descriptor(int wValue, int wIndex, int wLength)
|
||||
{
|
||||
static void sh7305_usb_request_get_descriptor(
|
||||
int wValue,
|
||||
int wIndex,
|
||||
size_t wLength
|
||||
) {
|
||||
usb_dc_device_t *dc_device;
|
||||
usb_dc_config_t *dc_config;
|
||||
usb_dc_interf_t *dc_interf;
|
||||
usb_dc_endpnt_t *dc_endpnt;
|
||||
int isidx;
|
||||
int ieidx;
|
||||
int esidx;
|
||||
int eeidx;
|
||||
int type;
|
||||
int indx;
|
||||
|
||||
|
@ -54,19 +60,60 @@ static void sh7305_usb_request_get_descriptor(int wValue, int wIndex, int wLengt
|
|||
type = (wValue & 0xff00) >> 8;
|
||||
indx = (wValue & 0x00ff) >> 0;
|
||||
|
||||
/* handle request description type */
|
||||
/* Return the DEVICE descriptor
|
||||
* @notes
|
||||
* - This is the first request, we only need to return the device
|
||||
* descriptor. */
|
||||
if (type == USB_REQ_DESCT_DEVICE) {
|
||||
usb_logger_write("DCP write DEVICE_DESC\n");
|
||||
sh7305_usb_dcp_write(
|
||||
&__sh7305_usb_dc_device,
|
||||
sizeof(struct usb_descriptor_device)
|
||||
);
|
||||
usb_logger_write("DCP write DEVICE_DESC (%04X)\n", wValue);
|
||||
if (usb_config_get_dc_device(&dc_device, indx) != 0) {
|
||||
sh7305_usb_request_error("unable to find the device descriptor\n");
|
||||
//FIXME : handle error
|
||||
}
|
||||
sh7305_usb_dcp_prepare();
|
||||
sh7305_usb_dcp_write(dc_device, sizeof(usb_dc_device_t));
|
||||
sh7305_usb_dcp_commit();
|
||||
return;
|
||||
}
|
||||
if (type == USB_REQ_DESCT_CONFIG) {
|
||||
sh7305_usb_request_unimplemented("GET_DESC_CONF", indx, 0, 0);
|
||||
|
||||
/* Return the CONFIGURATION descriptor
|
||||
* @notes
|
||||
* - this request is performed 2 times : on the first request, we should
|
||||
* return only the descriptor. On the second request, wLengh is set to
|
||||
* the .wTotalLengh and we should return the current configuration
|
||||
* descriptor and all of its interfaces / endpoints descriptors */
|
||||
if (type == USB_REQ_DESCT_CONFIG)
|
||||
{
|
||||
usb_logger_write("DCP write CONFIG_DESC (%d,%d)\n", indx, wLength);
|
||||
if (usb_config_get_dc_config(&dc_config, indx, &isidx, &ieidx) != 0) {
|
||||
sh7305_usb_request_error("- config %d not found\n", indx);
|
||||
//FIXME : handle error
|
||||
}
|
||||
sh7305_usb_dcp_prepare();
|
||||
sh7305_usb_dcp_write(dc_config, sizeof(usb_dc_config_t));
|
||||
if (wLength <= sizeof(usb_dc_config_t)) {
|
||||
sh7305_usb_dcp_commit();
|
||||
return;
|
||||
}
|
||||
for (int i = isidx ; i < ieidx ; i++) {
|
||||
if (usb_config_get_dc_interf(&dc_interf, i, &esidx, &eeidx) != 0) {
|
||||
sh7305_usb_request_error("- interface %d not found\n", i);
|
||||
//FIXME : handle error
|
||||
}
|
||||
sh7305_usb_dcp_write(dc_interf, sizeof(usb_dc_interf_t));
|
||||
for (int j = esidx ; j < eeidx ; ++j) {
|
||||
if (usb_config_get_dc_endpnt(&dc_endpnt, j) != 0) {
|
||||
sh7305_usb_request_error("- endpoint %d not found\n", j);
|
||||
//FIXME : handle error
|
||||
}
|
||||
sh7305_usb_dcp_write(dc_endpnt, sizeof(usb_dc_endpnt_t));
|
||||
}
|
||||
}
|
||||
sh7305_usb_dcp_commit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO : support all other request */
|
||||
if (type == USB_REQ_DESCT_STRING) {
|
||||
sh7305_usb_request_unimplemented("GET_DESC_STR", indx, 0, 0);
|
||||
return;
|
||||
|
@ -124,6 +171,8 @@ void sh7305_usb_request_handle(void)
|
|||
wIndex = SH7305_USB.USBINDX.word;
|
||||
wLength = SH7305_USB.USBLENG.word;
|
||||
|
||||
usb_logger_write("wLength = %d\n", SH7305_USB.USBLENG.word);
|
||||
|
||||
/* clear VALID bits */
|
||||
SH7305_USB_INTSTS0_CLEAR(VALID);
|
||||
|
||||
|
@ -174,9 +223,11 @@ void sh7305_usb_request_handle(void)
|
|||
return;
|
||||
}
|
||||
if (bRequest == SH7305_USB_REQT_SET_CONFIGURATION) {
|
||||
sh7305_usb_request_unimplemented(
|
||||
"SET_CONFIGURATION", wValue, wIndex, wLength
|
||||
);
|
||||
usb_logger_write("SET_CONFIGURATION<%d>", wIndex);
|
||||
sh7305_usb_dcp_prepare();
|
||||
usb_config_select_config(wIndex);
|
||||
//FIXME : proper DCP FIFO config and handle config selection error
|
||||
sh7305_usb_dcp_commit();
|
||||
return;
|
||||
}
|
||||
usb_logger_write("request: unable to resolve bRequest %d\n", bRequest);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <vhex/driver/mpu/sh/sh7305/cpg.h>
|
||||
#include <vhex/driver/mpu/sh/sh7305/tmu.h>
|
||||
#include <vhex/driver/mpu/sh/sh7305/power.h>
|
||||
#include <vhex/usb/interface.h>
|
||||
#include <vhex/driver.h>
|
||||
|
||||
//----
|
||||
|
@ -90,9 +91,13 @@ struct vhex_driver drv_usb = {
|
|||
.configure = NULL,
|
||||
.state_size = 4,
|
||||
.flags = {
|
||||
.USB = 1,
|
||||
.SHARED = 0,
|
||||
.UNUSED = 1,
|
||||
.USB = 1,
|
||||
.SHARED = 0,
|
||||
.UNUSED = 1,
|
||||
},
|
||||
.module_data = &(struct usb_drv_interface){
|
||||
.open = &sh7305_usb_open,
|
||||
.pipe_find = &sh7305_usb_pipe_find
|
||||
}
|
||||
};
|
||||
VHEX_DECLARE_DRIVER(06, drv_usb);
|
||||
|
|
|
@ -34,7 +34,7 @@ struct {
|
|||
|
||||
VCONSTRUCTOR static void __dtext_constructor(void)
|
||||
{
|
||||
dtext_info.pool.number = 16;
|
||||
dtext_info.pool.number = 32;
|
||||
dtext_info.pool.idx = -1;
|
||||
dtext_info.pool.text = calloc(
|
||||
dtext_info.pool.number,
|
||||
|
|
|
@ -20,8 +20,11 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in)
|
|||
cpu_atomic_start();
|
||||
dtable = vhex_driver_table();
|
||||
for (int i = 0; i < vhex_driver_count(); ++i) {
|
||||
if (dtable[i].hpowered != NULL
|
||||
&& dtable[i].hpowered() == false) {
|
||||
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false) {
|
||||
wout->driver[i].flags.UNUSED = 1;
|
||||
continue;
|
||||
}
|
||||
if (dtable[i].hsave == NULL) {
|
||||
wout->driver[i].flags.UNUSED = 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -37,15 +40,15 @@ int hypervisor_world_switch(hyp_world_t out, hyp_world_t in)
|
|||
}
|
||||
//FIXME : check shared driver
|
||||
if (win->driver[i].flags.UNUSED == 1) {
|
||||
if (dtable[i].hpowered() == true)
|
||||
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == true)
|
||||
dtable[i].hpoweroff();
|
||||
continue;
|
||||
}
|
||||
//FIXME : check if the driver is unused
|
||||
if (dtable[i].hpowered != NULL && dtable[i].hpowered() == false)
|
||||
dtable[i].hpoweron();
|
||||
dtable[i].hrestore(win->driver[i].context);
|
||||
|
||||
if (dtable[i].hrestore != NULL)
|
||||
dtable[i].hrestore(win->driver[i].context);
|
||||
}
|
||||
win->status.INIT = 1;
|
||||
win->status.ACTIVE = 1;
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
#include <vhex/usb/configuration.h>
|
||||
#include <vhex/usb/descriptor.h>
|
||||
#include <vhex/driver/cpu.h>
|
||||
#include <vhex/usb/utils.h>
|
||||
#include <vhex/usb/pipe.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//---
|
||||
// Internals
|
||||
// @TODO
|
||||
// - strict descriptor check
|
||||
// - proper return code error
|
||||
// - check if the USB connection is already setup
|
||||
// - configuration selector (SET_CONFIGURATION)
|
||||
//---
|
||||
|
||||
/* internal copy of each descriptor */
|
||||
static usb_dc_device_t usb_dc_device;
|
||||
static usb_dc_config_t usb_dc_config[__USB_MAX_DC_CONF];
|
||||
static usb_dc_interf_t usb_dc_interf[__USB_MAX_DC_INTR];
|
||||
static usb_dc_endpnt_t usb_dc_endpnt[__USB_MAX_DC_ENDP];
|
||||
|
||||
/* internals descriptor counter (used in request interrupt handler) */
|
||||
static int usb_dc_device_nb = 0;
|
||||
static int usb_dc_config_nb = 0;
|
||||
static int usb_dc_interf_nb = 0;
|
||||
static int usb_dc_endpnt_nb = 0;
|
||||
|
||||
/* usb_conf_check_conf() : check and patch interface desc. */
|
||||
static int usb_conf_check_endpoint(usb_dc_endpnt_t **endpoint, size_t *total)
|
||||
{
|
||||
int pipe_id;
|
||||
int i;
|
||||
|
||||
if (endpoint == NULL)
|
||||
return -3;
|
||||
for (i = 0 ; endpoint[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __USB_MAX_DC_ENDP) {
|
||||
usb_logger_write("- too many endpoint (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
*total += sizeof(usb_dc_endpnt_t);
|
||||
pipe_id = usb_pipe_find(endpoint[i]->bmAttributes.trans);
|
||||
if (pipe_id < 0)
|
||||
return pipe_id;
|
||||
endpoint[i]->bEndpointAddress.number = pipe_id;
|
||||
memcpy(
|
||||
&usb_dc_endpnt[usb_dc_endpnt_nb],
|
||||
endpoint[i],
|
||||
sizeof(usb_dc_endpnt_t)
|
||||
);
|
||||
usb_logger_write("- use pipe %d\n", pipe_id);
|
||||
usb_dc_endpnt_nb += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* usb_conf_check_conf() : check and patch interface desc. */
|
||||
static int usb_conf_check_interface(
|
||||
struct usb_full_interface **interface,
|
||||
size_t *total
|
||||
) {
|
||||
int nbendpoint;
|
||||
int i;
|
||||
|
||||
if (interface == NULL)
|
||||
return -3;
|
||||
for (i = 0 ; interface[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __USB_MAX_DC_INTR) {
|
||||
usb_logger_write("- too many interface (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
//FIXME : check strings
|
||||
*total += sizeof(usb_dc_interf_t);
|
||||
nbendpoint = usb_conf_check_endpoint(interface[i]->endpoint, total);
|
||||
if (nbendpoint < 0)
|
||||
return nbendpoint;
|
||||
interface[i]->descriptor->bInterfaceNumber = i;
|
||||
interface[i]->descriptor->bNumEndpoints = nbendpoint;
|
||||
memcpy(
|
||||
&usb_dc_interf[usb_dc_interf_nb],
|
||||
interface[i]->descriptor,
|
||||
sizeof(usb_dc_interf_t)
|
||||
);
|
||||
usb_logger_write("- use interface %d\n", usb_dc_interf_nb);
|
||||
usb_dc_interf_nb += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* usb_conf_check_conf() : check and patch configuration desc. */
|
||||
static int usb_conf_check_conf(struct usb_full_config **config)
|
||||
{
|
||||
int nbinterf;
|
||||
size_t total;
|
||||
int i;
|
||||
|
||||
if (config == NULL)
|
||||
return -2;
|
||||
for (i = 0 ; config[i] != NULL ; ++i)
|
||||
{
|
||||
if (i >= __USB_MAX_DC_CONF) {
|
||||
usb_logger_write("- too many configuration (%d)\n", i);
|
||||
return -4;
|
||||
}
|
||||
//FIXME : check strings
|
||||
total = sizeof(struct usb_descriptor_configuration);
|
||||
nbinterf = usb_conf_check_interface(config[i]->interface, &total);
|
||||
if (nbinterf < 0)
|
||||
return nbinterf;
|
||||
config[i]->descriptor->wTotalLengh = USB_WORD_TO(total);
|
||||
config[i]->descriptor->bConfigurationValue = i;
|
||||
config[i]->descriptor->bNumInterfaces = nbinterf;
|
||||
memcpy(
|
||||
&usb_dc_config[usb_dc_config_nb],
|
||||
config[i]->descriptor,
|
||||
sizeof(usb_dc_config_t)
|
||||
);
|
||||
usb_logger_write(
|
||||
"- use configuration %d with %d interface\n",
|
||||
usb_dc_config_nb,
|
||||
nbinterf
|
||||
);
|
||||
usb_dc_config_nb += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* usb_config_resolve() : check and resolve USB configuration */
|
||||
int usb_config_resolve(struct usb_full_device *device)
|
||||
{
|
||||
int nbconf;
|
||||
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
|
||||
//FIXME : check if the USB connection is already set
|
||||
//FIXME : check string validity
|
||||
|
||||
cpu_atomic_start();
|
||||
|
||||
/* USB descriptor counter reset */
|
||||
usb_dc_device_nb = 1;
|
||||
usb_dc_config_nb = 0;
|
||||
usb_dc_interf_nb = 0;
|
||||
usb_dc_endpnt_nb = 0;
|
||||
|
||||
|
||||
/* patch configuration descriptors */
|
||||
nbconf = usb_conf_check_conf(device->config);
|
||||
if (nbconf < 0)
|
||||
return nbconf;
|
||||
|
||||
/* patch device descriptor */
|
||||
device->descriptor->bNumConfigurations = nbconf;
|
||||
memcpy(&usb_dc_device, device->descriptor, sizeof(usb_dc_device_t));
|
||||
|
||||
cpu_atomic_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* usb_config_select_config() : try to selecte a configuration */
|
||||
int usb_config_select_config(int idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
|
||||
cpu_atomic_start();
|
||||
ret = (idx < usb_dc_config_nb) ? 0 : -2;
|
||||
//TODO : real configuration selection
|
||||
cpu_atomic_end();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* usb_config_get_dc_device() : get device descriptor */
|
||||
int usb_config_get_dc_device(usb_dc_device_t **dc_device, int idx)
|
||||
{
|
||||
if (dc_device == NULL)
|
||||
return -1;
|
||||
if (idx != 0) {
|
||||
*dc_device = NULL;
|
||||
return -2;
|
||||
}
|
||||
*dc_device = &usb_dc_device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* usb_config_get_dc_config() : get config descriptor */
|
||||
int usb_config_get_dc_config(
|
||||
usb_dc_config_t **dc_config,
|
||||
int idx,
|
||||
int *isidx,
|
||||
int *ieidx
|
||||
) {
|
||||
int ret;
|
||||
int start;
|
||||
int end;
|
||||
|
||||
if (dc_config == NULL)
|
||||
return -1;
|
||||
if (idx < 0)
|
||||
return -2;
|
||||
|
||||
cpu_atomic_start();
|
||||
ret = -3;
|
||||
*dc_config = NULL;
|
||||
if (idx < usb_dc_config_nb) {
|
||||
start = 0;
|
||||
for (int i = 0 ; i < idx ; ++i) {
|
||||
start += usb_dc_config[i].bNumInterfaces;
|
||||
}
|
||||
end = start + usb_dc_config[idx].bNumInterfaces;
|
||||
*dc_config = &usb_dc_config[idx];
|
||||
if (isidx != NULL) *isidx = start;
|
||||
if (ieidx != NULL) *ieidx = end;
|
||||
ret = 0;
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* usb_config_get_dc_interf() : get interface descriptor */
|
||||
int usb_config_get_dc_interf(
|
||||
usb_dc_interf_t **dc_interf,
|
||||
int idx,
|
||||
int *esidx,
|
||||
int *eeidx
|
||||
) {
|
||||
int ret;
|
||||
int start;
|
||||
int end;
|
||||
|
||||
if (dc_interf == NULL)
|
||||
return -1;
|
||||
if (idx < 0)
|
||||
return -2;
|
||||
|
||||
cpu_atomic_start();
|
||||
ret = -3;
|
||||
*dc_interf = NULL;
|
||||
if (idx < usb_dc_interf_nb) {
|
||||
start = 0;
|
||||
for (int i = 0 ; i < idx ; ++i) {
|
||||
start += usb_dc_interf[i].bNumEndpoints;
|
||||
}
|
||||
end = start + usb_dc_interf[idx].bNumEndpoints;
|
||||
*dc_interf = &usb_dc_interf[idx];
|
||||
if (esidx != NULL) *esidx = start;
|
||||
if (eeidx != NULL) *eeidx = end;
|
||||
ret = 0;
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* usb_config_get_dc_endpoint() : get endpoint descriptor */
|
||||
int usb_config_get_dc_endpnt(usb_dc_endpnt_t **dc_endpnt, int idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dc_endpnt == NULL)
|
||||
return -1;
|
||||
|
||||
cpu_atomic_start();
|
||||
ret = -2;
|
||||
*dc_endpnt = NULL;
|
||||
if (idx < usb_dc_endpnt_nb) {
|
||||
*dc_endpnt = &usb_dc_endpnt[idx];
|
||||
ret = 0;
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <vhex/usb/info.h>
|
||||
#include <vhex/usb.h>
|
||||
#include <vhex/driver/cpu.h>
|
||||
|
||||
/* TODO : isolate */
|
||||
#include <string.h>
|
||||
|
||||
extern bool usb_logger_attached;
|
||||
extern usb_logger_t usb_logger;
|
||||
/* internal module information */
|
||||
extern struct usb_mod_info usb_mod_info;
|
||||
|
||||
//---
|
||||
// Public API
|
||||
|
@ -15,7 +14,7 @@ extern usb_logger_t usb_logger;
|
|||
/* usb_logger_set() : return true if a logger is attached */
|
||||
bool usb_logger_is_attached(void)
|
||||
{
|
||||
return usb_logger_attached;
|
||||
return usb_mod_info.logger.attached;
|
||||
}
|
||||
|
||||
/* usb_logger_set() : attach a logger to the kernel USB driver (clear) */
|
||||
|
@ -28,14 +27,14 @@ int usb_logger_attach(usb_logger_t *logger, size_t buffer_size)
|
|||
|
||||
cpu_atomic_start();
|
||||
ret = -2;
|
||||
if (usb_logger_attached == false) {
|
||||
if (usb_mod_info.logger.attached == false) {
|
||||
ret = -3;
|
||||
if (logger->primitive.init != NULL)
|
||||
ret = logger->primitive.init(logger, buffer_size);
|
||||
}
|
||||
if (ret == 0) {
|
||||
memcpy(&usb_logger, logger, sizeof(usb_logger_t));
|
||||
usb_logger_attached = true;
|
||||
memcpy(&usb_mod_info.logger.device, logger, sizeof(usb_logger_t));
|
||||
usb_mod_info.logger.attached = true;
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
|
@ -49,10 +48,13 @@ int usb_logger_clear(void)
|
|||
|
||||
cpu_atomic_start();
|
||||
ret = -1;
|
||||
if (usb_logger_attached == true) {
|
||||
if (usb_mod_info.logger.attached == true) {
|
||||
ret = -2;
|
||||
if (usb_logger.primitive.clear != NULL)
|
||||
ret = usb_logger.primitive.clear(&usb_logger);
|
||||
if (usb_mod_info.logger.device.primitive.clear != NULL) {
|
||||
ret = usb_mod_info.logger.device.primitive.clear(
|
||||
&usb_mod_info.logger.device
|
||||
);
|
||||
}
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
|
@ -69,10 +71,14 @@ ssize_t usb_logger_write(char *format, ...)
|
|||
|
||||
cpu_atomic_start();
|
||||
ret = -1;
|
||||
if (usb_logger_attached == true) {
|
||||
if (usb_mod_info.logger.attached == true) {
|
||||
ret = -2;
|
||||
if (usb_logger.primitive.write != NULL)
|
||||
ret = usb_logger.primitive.write(&usb_logger, format, ap);
|
||||
if (usb_mod_info.logger.device.primitive.write != NULL)
|
||||
ret = usb_mod_info.logger.device.primitive.write(
|
||||
&usb_mod_info.logger.device,
|
||||
format,
|
||||
ap
|
||||
);
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
|
@ -88,10 +94,14 @@ ssize_t usb_logger_getline(char **lineptr, size_t *n)
|
|||
|
||||
cpu_atomic_start();
|
||||
ret = -1;
|
||||
if (usb_logger_attached == true) {
|
||||
if (usb_mod_info.logger.attached == true) {
|
||||
ret = -2;
|
||||
if (usb_logger.primitive.getline != NULL)
|
||||
ret = usb_logger.primitive.getline(&usb_logger, lineptr, n);
|
||||
if (usb_mod_info.logger.device.primitive.getline != NULL)
|
||||
ret = usb_mod_info.logger.device.primitive.getline(
|
||||
&usb_mod_info.logger.device,
|
||||
lineptr,
|
||||
n
|
||||
);
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
|
@ -105,14 +115,16 @@ int usb_logger_detach(void)
|
|||
|
||||
cpu_atomic_start();
|
||||
ret = -1;
|
||||
if (usb_logger_attached == true) {
|
||||
if (usb_mod_info.logger.attached == true) {
|
||||
ret = -2;
|
||||
if (usb_logger.primitive.quit != NULL)
|
||||
ret = usb_logger.primitive.quit(&usb_logger);
|
||||
if (usb_mod_info.logger.device.primitive.quit != NULL)
|
||||
ret = usb_mod_info.logger.device.primitive.quit(
|
||||
&usb_mod_info.logger.device
|
||||
);
|
||||
}
|
||||
if (ret == 0) {
|
||||
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
|
||||
usb_logger_attached = false;
|
||||
memset(&usb_mod_info.logger.device, 0x00, sizeof(usb_logger_t));
|
||||
usb_mod_info.logger.attached = false;
|
||||
}
|
||||
cpu_atomic_end();
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#include <vhex/usb/info.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
/* internal module information */
|
||||
extern struct usb_mod_info usb_mod_info;
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* usb_pipe_find() : find a pipe of type `type` */
|
||||
int usb_pipe_find(int type)
|
||||
{
|
||||
if (usb_mod_info.driver.pipe_find != NULL)
|
||||
return usb_mod_info.driver.pipe_find(type);
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#include <vhex/usb/info.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
/* internal module information */
|
||||
extern struct usb_mod_info usb_mod_info;
|
||||
|
||||
//---
|
||||
// Public API
|
||||
//---
|
||||
|
||||
/* usb_open() : open primitive */
|
||||
int usb_open(struct usb_full_device *device)
|
||||
{
|
||||
if (usb_mod_info.driver.open != NULL)
|
||||
return usb_mod_info.driver.open(device);
|
||||
return -1;
|
||||
}
|
|
@ -1,29 +1,42 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <vhex/usb.h>
|
||||
#include <vhex/driver.h>
|
||||
#include <vhex/module.h>
|
||||
#include <vhex/usb/interface.h>
|
||||
#include <vhex/usb/info.h>
|
||||
#include <vhex/usb.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//---
|
||||
// Kernel module information
|
||||
//---
|
||||
|
||||
/* Internal USB driver information */
|
||||
bool usb_logger_attached;
|
||||
usb_logger_t usb_logger;
|
||||
/* internal USB driver information */
|
||||
struct usb_mod_info usb_mod_info;
|
||||
|
||||
/* __timer_init() : initialize the timer module */
|
||||
/* __usb_init() : initialize the usb module */
|
||||
static void __usb_init(void)
|
||||
{
|
||||
usb_logger_attached = false;
|
||||
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
|
||||
struct vhex_driver *driver;
|
||||
|
||||
memset(&usb_mod_info, 0x00, sizeof(usb_mod_info));
|
||||
|
||||
driver = vhex_driver_table();
|
||||
for (int i = 0; i < vhex_driver_count(); ++i) {
|
||||
if (driver[i].flags.USB) {
|
||||
memcpy(
|
||||
&usb_mod_info.driver,
|
||||
driver[i].module_data,
|
||||
sizeof(struct usb_drv_interface)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* __timer_quit() : uninitialize the timer module */
|
||||
/* __usb_quit() : uninitialize the usb module */
|
||||
static void __usb_quit(void)
|
||||
{
|
||||
memset(&usb_logger, 0x00, sizeof(usb_logger_t));
|
||||
usb_logger_attached = false;
|
||||
memset(&usb_mod_info, 0x00, sizeof(usb_mod_info));
|
||||
}
|
||||
|
||||
/* declare the timer module */
|
||||
|
@ -32,5 +45,6 @@ struct vhex_module mod_usb = {
|
|||
.name = "USB",
|
||||
.init = &__usb_init,
|
||||
.quit = &__usb_quit,
|
||||
|
||||
};
|
||||
VHEX_DECLARE_MODULE(06, mod_usb);
|
||||
|
|
2
vxdev
2
vxdev
|
@ -1,3 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
python3 scripts/vxdev $@
|
||||
/usr/bin/env python3 scripts/vxdev $@
|
||||
|
|
|
@ -9,7 +9,7 @@ target = [
|
|||
|
||||
[build]
|
||||
configure = './vxdev configure'
|
||||
build = './vxdev build'
|
||||
build = './vxdev build --verbose'
|
||||
install = './vxdev install'
|
||||
uninstall = './vxdev uninstall'
|
||||
|
||||
|
@ -31,7 +31,8 @@ assets_prefix = [
|
|||
'-mb',
|
||||
'-m4-nofpu',
|
||||
'-fstrict-volatile-bitfields',
|
||||
'-Wa,--dsp'
|
||||
'-Wa,--dsp',
|
||||
'-fstack-protector-all',
|
||||
]
|
||||
VXSDK_PUBLIC_BUILD_LIBS = [
|
||||
'@COMMON@',
|
||||
|
@ -40,7 +41,8 @@ assets_prefix = [
|
|||
'-Wl,--no-whole-archive',
|
||||
'@sh-elf-vhex@',
|
||||
'-lc',
|
||||
'-lgcc'
|
||||
'-lgcc',
|
||||
'-lssp_nonshared',
|
||||
]
|
||||
VXSDK_PUBLIC_BUILD_LDFLAGS = [
|
||||
'-T {VXSDK_CURRENT_SOURCE_DIR}/boards/fxcg50/fxcg50.ld',
|
||||
|
|
Loading…
Reference in New Issue