Merge pull request #117 from dismirlian/usbh_devel

USB Host update
This commit is contained in:
Fabien Poussin 2017-06-07 11:26:30 +02:00 committed by GitHub
commit 46a0296ed6
39 changed files with 4358 additions and 6965 deletions

View File

@ -19,3 +19,7 @@ https://github.com/mabl
Andrea Zoppi aka TexZK
https://github.com/TexZK
Diego Ismirlian aka dismirlian
https://github.com/dismirlian
USB Host stack author

View File

@ -12,6 +12,8 @@ HALSRC += ${CHIBIOS_CONTRIB}/os/hal/src/hal_community.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_hub.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_msd.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_ftdi.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_aoa.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_hid.c \
${CHIBIOS_CONTRIB}/os/hal/src/usbh/hal_usbh_uvc.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_ee24xx.c \
${CHIBIOS_CONTRIB}/os/hal/src/hal_ee25xx.c \

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -20,6 +20,9 @@
#include "hal.h"
#ifndef HAL_USE_USBH
#define HAL_USE_USBH FALSE
#endif
#ifndef HAL_USBH_USE_FTDI
#define HAL_USBH_USE_FTDI FALSE
@ -37,6 +40,16 @@
#define HAL_USBH_USE_UVC FALSE
#endif
#ifndef HAL_USBH_USE_AOA
#define HAL_USBH_USE_AOA FALSE
#endif
#ifndef HAL_USBH_USE_HID
#define HAL_USBH_USE_HID FALSE
#endif
#define HAL_USBH_USE_IAD HAL_USBH_USE_UVC
#if (HAL_USE_USBH == TRUE) || defined(__DOXYGEN__)
#include "osal.h"
@ -104,13 +117,11 @@ enum usbh_urbstatus {
USBH_URBSTATUS_UNINITIALIZED = 0,
USBH_URBSTATUS_INITIALIZED,
USBH_URBSTATUS_PENDING,
// USBH_URBSTATUS_QUEUED,
USBH_URBSTATUS_ERROR,
USBH_URBSTATUS_TIMEOUT,
USBH_URBSTATUS_CANCELLED,
USBH_URBSTATUS_STALL,
USBH_URBSTATUS_DISCONNECTED,
// USBH_URBSTATUS_EPCLOSED,
USBH_URBSTATUS_OK,
};
@ -145,7 +156,8 @@ typedef void (*usbh_completion_cb)(usbh_urb_t *);
/* include the low level driver; the required definitions are above */
#include "hal_usbh_lld.h"
#define USBH_DEFINE_BUFFER(type, name) USBH_LLD_DEFINE_BUFFER(type, name)
#define USBH_DEFINE_BUFFER(var) USBH_LLD_DEFINE_BUFFER(var)
#define USBH_DECLARE_STRUCT_MEMBER(member) USBH_LLD_DECLARE_STRUCT_MEMBER(member)
struct usbh_urb {
usbh_ep_t *ep;
@ -198,9 +210,8 @@ struct usbh_device {
usbh_devstatus_t status;
usbh_devspeed_t speed;
USBH_DEFINE_BUFFER(usbh_device_descriptor_t, devDesc);
unsigned char align_bytes[2];
USBH_DEFINE_BUFFER(usbh_config_descriptor_t, basicConfigDesc);
USBH_DECLARE_STRUCT_MEMBER(usbh_device_descriptor_t devDesc);
USBH_DECLARE_STRUCT_MEMBER(usbh_config_descriptor_t basicConfigDesc);
uint8_t *fullConfigurationDescriptor;
uint8_t keepFullCfgDesc;
@ -362,11 +373,7 @@ extern "C" {
usbhEPCloseS(ep);
osalSysUnlock();
}
static inline void usbhEPResetI(usbh_ep_t *ep) {
osalDbgCheckClassI();
osalDbgCheck(ep != NULL);
usbh_lld_epreset(ep);
}
bool usbhEPReset(usbh_ep_t *ep);
static inline bool usbhEPIsPeriodic(usbh_ep_t *ep) {
osalDbgCheck(ep != NULL);
return (ep->type & 1) != 0;

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -23,8 +23,6 @@
#if HAL_USE_USBH
//TODO: Debug is only for USBHD1, make it generic.
#if USBH_DEBUG_ENABLE
void usbDbgPrintf(const char *fmt, ...);
void usbDbgPuts(const char *s);

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -25,12 +25,12 @@
#include "osal.h"
#ifdef __IAR_SYSTEMS_ICC__
#define PACKED_STRUCT typedef PACKED_VAR struct
#define PACKED_STRUCT PACKED_VAR struct
#else
#define PACKED_STRUCT typedef struct PACKED_VAR
#define PACKED_STRUCT struct PACKED_VAR
#endif
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
@ -49,7 +49,7 @@ PACKED_STRUCT {
#define USBH_DT_DEVICE 0x01
#define USBH_DT_DEVICE_SIZE 18
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
@ -62,7 +62,7 @@ PACKED_STRUCT {
#define USBH_DT_CONFIG 0x02
#define USBH_DT_CONFIG_SIZE 9
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData[1];
@ -70,7 +70,7 @@ PACKED_STRUCT {
#define USBH_DT_STRING 0x03
#define USBH_DT_STRING_SIZE 2
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
@ -84,7 +84,7 @@ PACKED_STRUCT {
#define USBH_DT_INTERFACE 0x04
#define USBH_DT_INTERFACE_SIZE 9
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
@ -95,7 +95,7 @@ PACKED_STRUCT {
#define USBH_DT_ENDPOINT 0x05
#define USBH_DT_ENDPOINT_SIZE 7
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bFirstInterface;
@ -108,7 +108,7 @@ PACKED_STRUCT {
#define USBH_DT_INTERFACE_ASSOCIATION 0x0b
#define USBH_DT_INTERFACE_ASSOCIATION_SIZE 8
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bDescLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
@ -120,7 +120,7 @@ PACKED_STRUCT {
#define USBH_DT_HUB 0x29
#define USBH_DT_HUB_SIZE (7 + 4)
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
@ -141,18 +141,17 @@ PACKED_STRUCT {
#define USBH_REQ_SET_INTERFACE 0x0B
#define USBH_REQ_SYNCH_FRAME 0x0C
#define USBH_REQTYPE_DIR_IN 0x80
#define USBH_REQTYPE_DIR_OUT 0x00
#define USBH_REQTYPE_IN 0x80
#define USBH_REQTYPE_OUT 0x00
#define USBH_REQTYPE_TYPE_STANDARD 0x00
#define USBH_REQTYPE_TYPE_CLASS 0x20
#define USBH_REQTYPE_TYPE_VENDOR 0x40
#define USBH_REQTYPE_STANDARD 0x00
#define USBH_REQTYPE_CLASS 0x20
#define USBH_REQTYPE_VENDOR 0x40
#define USBH_REQTYPE_DEVICE 0x00
#define USBH_REQTYPE_INTERFACE 0x01
#define USBH_REQTYPE_ENDPOINT 0x02
#define USBH_REQTYPE_OTHER 0x03
#define USBH_REQTYPE_RECIP_DEVICE 0x00
#define USBH_REQTYPE_RECIP_INTERFACE 0x01
#define USBH_REQTYPE_RECIP_ENDPOINT 0x02
#define USBH_REQTYPE_RECIP_OTHER 0x03
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -0,0 +1,156 @@
/*
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef USBH_AOA_H_
#define USBH_AOA_H_
#include "hal_usbh.h"
#if HAL_USE_USBH && HAL_USBH_USE_AOA
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
typedef enum {
USBHAOA_CHANNEL_STATE_UNINIT = 0,
USBHAOA_CHANNEL_STATE_STOP = 1,
USBHAOA_CHANNEL_STATE_ACTIVE = 2,
USBHAOA_CHANNEL_STATE_READY = 3
} usbhaoa_channel_state_t;
typedef enum {
USBHAOA_STATE_UNINIT = 0,
USBHAOA_STATE_STOP = 1,
USBHAOA_STATE_ACTIVE = 2,
USBHAOA_STATE_READY = 3
} usbhaoa_state_t;
typedef enum {
USBHAOA_AUDIO_MODE_DISABLED = 0,
USBHAOA_AUDIO_MODE_2CH_16BIT_PCM_44100 = 1,
} usbhaoa_audio_mode_t;
typedef struct {
struct _aoa_channel_cfg {
const char *manufacturer;
const char *model;
const char *description;
const char *version;
const char *uri;
const char *serial;
} channel;
struct _aoa_audio_cfg {
usbhaoa_audio_mode_t mode;
} audio;
} USBHAOAConfig;
#define _aoa_driver_methods \
_base_asynchronous_channel_methods
struct AOADriverVMT {
_aoa_driver_methods
};
typedef struct USBHAOAChannel USBHAOAChannel;
typedef struct USBHAOADriver USBHAOADriver;
struct USBHAOAChannel {
/* inherited from abstract asyncrhonous channel driver */
const struct AOADriverVMT *vmt;
_base_asynchronous_channel_data
usbh_ep_t epin;
usbh_urb_t iq_urb;
threads_queue_t iq_waiting;
uint32_t iq_counter;
USBH_DECLARE_STRUCT_MEMBER(uint8_t iq_buff[64]);
uint8_t *iq_ptr;
usbh_ep_t epout;
usbh_urb_t oq_urb;
threads_queue_t oq_waiting;
uint32_t oq_counter;
USBH_DECLARE_STRUCT_MEMBER(uint8_t oq_buff[64]);
uint8_t *oq_ptr;
virtual_timer_t vt;
usbhaoa_channel_state_t state;
};
struct USBHAOADriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
USBHAOAChannel channel;
usbhaoa_state_t state;
};
#define USBHAOA_ACCESSORY_STRING_MANUFACTURER 0
#define USBHAOA_ACCESSORY_STRING_MODEL 1
#define USBHAOA_ACCESSORY_STRING_DESCRIPTION 2
#define USBHAOA_ACCESSORY_STRING_VERSION 3
#define USBHAOA_ACCESSORY_STRING_URI 4
#define USBHAOA_ACCESSORY_STRING_SERIAL 5
typedef bool (*usbhaoa_filter_callback_t)(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem, USBHAOAConfig *config);
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
#define usbhaoaStop(aoap)
#define usbhaoaGetState(aoap) ((aoap)->state)
#define usbhaoaGetChannelState(aoap) ((aoap)->channel.state)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern USBHAOADriver USBHAOAD[HAL_USBHAOA_MAX_INSTANCES];
#ifdef __cplusplus
extern "C" {
#endif
/* AOA device driver */
void usbhaoaObjectInit(USBHAOADriver *aoap);
void usbhaoaChannelStart(USBHAOADriver *aoap);
void usbhaoaChannelStop(USBHAOADriver *aoap);
/* global initializer */
void usbhaoaInit(void);
#ifdef __cplusplus
}
#endif
#endif
#endif /* USBH_AOA_H_ */

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -96,7 +96,7 @@ struct USBHFTDIPortDriver {
usbh_urb_t iq_urb;
threads_queue_t iq_waiting;
uint32_t iq_counter;
USBH_DEFINE_BUFFER(uint8_t, iq_buff[64]);
USBH_DECLARE_STRUCT_MEMBER(uint8_t iq_buff[64]);
uint8_t *iq_ptr;
@ -104,7 +104,7 @@ struct USBHFTDIPortDriver {
usbh_urb_t oq_urb;
threads_queue_t oq_waiting;
uint32_t oq_counter;
USBH_DEFINE_BUFFER(uint8_t, oq_buff[64]);
USBH_DECLARE_STRUCT_MEMBER(uint8_t oq_buff[64]);
uint8_t *oq_ptr;
virtual_timer_t vt;
@ -113,7 +113,7 @@ struct USBHFTDIPortDriver {
USBHFTDIPortDriver *next;
};
typedef struct USBHFTDIDriver {
struct USBHFTDIDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
@ -121,11 +121,12 @@ typedef struct USBHFTDIDriver {
USBHFTDIPortDriver *ports;
mutex_t mtx;
} USBHFTDIDriver;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
#define usbhftdipGetState(ftdipp) ((ftdipp)->state)
/*===========================================================================*/
@ -144,6 +145,9 @@ extern "C" {
void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp);
void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config);
void usbhftdipStop(USBHFTDIPortDriver *ftdipp);
/* global initializer */
void usbhftdiInit(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,148 @@
/*
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef USBH_HID_H_
#define USBH_HID_H_
#include "hal_usbh.h"
#if HAL_USE_USBH && HAL_USBH_USE_HID
/* TODO:
*
*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
#if !defined(HAL_USBHHID_USE_INTERRUPT_OUT)
#define HAL_USBHHID_USE_INTERRUPT_OUT FALSE
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
typedef enum {
USBHHID_STATE_UNINIT = 0,
USBHHID_STATE_STOP = 1,
USBHHID_STATE_ACTIVE = 2,
USBHHID_STATE_READY = 3
} usbhhid_state_t;
typedef enum {
USBHHID_DEVTYPE_GENERIC = 0,
USBHHID_DEVTYPE_BOOT_KEYBOARD = 1,
USBHHID_DEVTYPE_BOOT_MOUSE = 2,
} usbhhid_devtype_t;
typedef enum {
USBHHID_REPORTTYPE_INPUT = 1,
USBHHID_REPORTTYPE_OUTPUT = 2,
USBHHID_REPORTTYPE_FEATURE = 3,
} usbhhid_reporttype_t;
typedef enum {
USBHHID_PROTOCOL_BOOT = 0,
USBHHID_PROTOCOL_REPORT = 1,
} usbhhid_protocol_t;
typedef struct USBHHIDDriver USBHHIDDriver;
typedef struct USBHHIDConfig USBHHIDConfig;
typedef void (*usbhhid_report_callback)(USBHHIDDriver *hidp, uint16_t len);
struct USBHHIDConfig {
usbhhid_report_callback cb_report;
void *report_buffer;
uint16_t report_len;
usbhhid_protocol_t protocol;
};
struct USBHHIDDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
usbh_ep_t epin;
#if HAL_USBHHID_USE_INTERRUPT_OUT
usbh_ep_t epout;
#endif
uint8_t ifnum;
usbhhid_devtype_t type;
usbhhid_state_t state;
usbh_urb_t in_urb;
const USBHHIDConfig *config;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES];
#ifdef __cplusplus
extern "C" {
#endif
/* HID Driver */
void usbhHIDObjectInit(USBHHIDDriver *hidp);
/* HID Common API */
usbh_urbstatus_t usbhhidGetReport(USBHHIDDriver *hidp,
uint8_t report_id, usbhhid_reporttype_t report_type,
void *data, uint16_t len);
usbh_urbstatus_t usbhhidSetReport(USBHHIDDriver *hidp,
uint8_t report_id, usbhhid_reporttype_t report_type,
const void *data, uint16_t len);
usbh_urbstatus_t usbhhidGetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t *duration);
usbh_urbstatus_t usbhhidSetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t duration);
usbh_urbstatus_t usbhhidGetProtocol(USBHHIDDriver *hidp, uint8_t *protocol);
usbh_urbstatus_t usbhhidSetProtocol(USBHHIDDriver *hidp, uint8_t protocol);
static inline uint8_t usbhhidGetType(USBHHIDDriver *hidp) {
return hidp->type;
}
static inline usbhhid_state_t usbhhidGetState(USBHHIDDriver *hidp) {
return hidp->state;
}
void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg);
/* global initializer */
void usbhhidInit(void);
#ifdef __cplusplus
}
#endif
#endif
#endif /* USBH_HID_H_ */

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -23,7 +23,7 @@
#if HAL_USE_USBH
#if HAL_USBH_USE_HUB
typedef struct USBHHubDriver {
struct USBHHubDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
@ -32,19 +32,19 @@ typedef struct USBHHubDriver {
usbh_ep_t epint;
usbh_urb_t urb;
USBH_DEFINE_BUFFER(uint8_t, scbuff[4]);
USBH_DECLARE_STRUCT_MEMBER(uint8_t scbuff[4]);
volatile uint32_t statuschange;
uint16_t status;
uint16_t c_status;
usbh_port_t *ports;
USBH_DEFINE_BUFFER(usbh_hub_descriptor_t, hubDesc);
USBH_DECLARE_STRUCT_MEMBER(usbh_hub_descriptor_t hubDesc);
/* Low level part */
_usbh_hub_ll_data
} USBHHubDriver;
};
extern USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES];
@ -60,7 +60,7 @@ usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host, USBHHubDriver *hub,
static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host, port->hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_CLEAR_FEATURE,
feature,
port->number,
@ -70,7 +70,7 @@ static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_
static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, USBHHubDriver *hub, uint8_t feature) {
return usbhhubControlRequest(host, hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE,
USBH_REQ_CLEAR_FEATURE,
feature,
0,
@ -80,7 +80,7 @@ static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, USBHHubD
static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host, port->hub,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_SET_FEATURE,
feature,
port->number,
@ -89,6 +89,9 @@ static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t
}
void usbhhubObjectInit(USBHHubDriver *hubdp);
void usbhhubInit(void);
#else
static inline usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host,
@ -103,7 +106,7 @@ static inline usbh_urbstatus_t usbhhubControlRequest(USBHDriver *host,
static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_CLEAR_FEATURE,
feature,
port->number,
@ -113,7 +116,7 @@ static inline usbh_urbstatus_t usbhhubClearFeaturePort(usbh_port_t *port, uint8_
static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, uint8_t feature) {
return usbhhubControlRequest(host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE,
USBH_REQ_CLEAR_FEATURE,
feature,
0,
@ -123,7 +126,7 @@ static inline usbh_urbstatus_t usbhhubClearFeatureHub(USBHDriver *host, uint8_t
static inline usbh_urbstatus_t usbhhubSetFeaturePort(usbh_port_t *port, uint8_t feature) {
return usbhhubControlRequest(port->device.host,
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_SET_FEATURE,
feature,
port->number,

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -25,7 +25,6 @@
/* TODO:
*
* - Implement of conditional compilation of multiple-luns per instance.
* - Implement error checking and recovery when commands fail.
*
*/
@ -65,7 +64,7 @@ struct USBHMassStorageLUNDriver {
USBHMassStorageLUNDriver *next;
};
typedef struct USBHMassStorageDriver {
struct USBHMassStorageDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
@ -81,7 +80,7 @@ typedef struct USBHMassStorageDriver {
uint32_t tag;
USBHMassStorageLUNDriver *luns;
} USBHMassStorageDriver;
};
/*===========================================================================*/
@ -116,6 +115,9 @@ extern "C" {
bool usbhmsdLUNGetInfo(USBHMassStorageLUNDriver *lunp, BlockDeviceInfo *bdip);
bool usbhmsdLUNIsInserted(USBHMassStorageLUNDriver *lunp);
bool usbhmsdLUNIsProtected(USBHMassStorageLUNDriver *lunp);
/* global initializer */
void usbhmsdInit(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,471 @@
/*
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef USBH_INCLUDE_USBH_UVC_H_
#define USBH_INCLUDE_USBH_UVC_H_
#include "hal_usbh.h"
#if HAL_USE_USBH && HAL_USBH_USE_UVC
/* TODO:
*
*
*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define USBHUVC_MAX_STATUS_PACKET_SZ 16
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
typedef enum {
UVC_CS_INTERFACE = 0x24,
UVC_CS_ENDPOINT = 0x25
} usbh_uvc_cstype_t;
typedef enum {
UVC_CC_VIDEO = 0x0e
} usbh_uvc_cctype_t;
typedef enum {
UVC_SC_UNKNOWN = 0x00,
UVC_SC_VIDEOCONTROL,
UVC_SC_VIDEOSTREAMING,
UVC_SC_VIDEO_INTERFACE_COLLECTION
} usbh_uvc_sctype_t;
typedef enum {
UVC_VC_UNDEF = 0x00,
UVC_VC_HEADER,
UVC_VC_INPUT_TERMINAL,
UVC_VC_OUTPUT_TERMINAL,
UVC_VC_SELECTOR_UNIT,
UVC_VC_PROCESSING_UNIT,
UVC_VC_EXTENSION_UNIT
} usbh_uvc_vctype_t;
typedef enum {
UVC_VS_UNDEF = 0x00,
UVC_VS_INPUT_HEADER,
UVC_VS_OUTPUT_HEADER,
UVC_VS_STILL_IMAGE_FRAME,
UVC_VS_FORMAT_UNCOMPRESSED,
UVC_VS_FRAME_UNCOMPRESSED,
UVC_VS_FORMAT_MJPEG,
UVC_VS_FRAME_MJPEG,
UVC_VS_RESERVED_0,
UVC_VS_RESERVED_1,
UVC_VS_FORMAT_MPEG2TS,
UVC_VS_RESERVED_2,
UVC_VS_FORMAT_DV,
UVC_VS_COLOR_FORMAT,
UVC_VS_RESERVED_3,
UVC_VS_RESERVED_4,
UVC_VS_FORMAT_FRAME_BASED,
UVC_VS_FRAME_FRAME_BASED,
UVC_VS_FORMAT_STREAM_BASED
} usbh_uvc_vstype_t;
typedef enum {
UVC_TT_VENDOR_SPECIFIC = 0x0100,
UVC_TT_STREAMING = 0x0101,
UVC_ITT_VENDOR_SPECIFIC = 0x0200,
UVC_ITT_CAMERA = 0x0201,
UVC_ITT_MEDIA_TRANSPORT_INPUT = 0x0202,
UVC_OTT_VENDOR_SPECIFIC = 0x0300,
UVC_OTT_DISPLAY = 0x0301,
UVC_OTT_MEDIA_TRANSPORT = 0x0302
} usbh_uvc_tttype_t;
typedef enum {
UVC_SET_CUR = 0x01,
UVC_GET_CUR = 0x81,
UVC_GET_MIN = 0x82,
UVC_GET_MAX = 0x83,
UVC_GET_RES = 0x84,
UVC_GET_LEN = 0x85,
UVC_GET_INFO = 0x86,
UVC_GET_DEF = 0x87
} usbh_uvc_ctrlops_t;
typedef enum {
UVC_CTRL_VC_CONTROL_UNDEFINED = 0x00,
UVC_CTRL_VC_VIDEO_POWER_MODE_CONTROL = 0x01,
UVC_CTRL_VC_REQUEST_ERROR_CODE_CONTROL = 0x02,
} usbh_uvc_ctrl_vc_interface_controls_t;
typedef enum {
UVC_CTRL_SU_CONTROL_UNDEFINED = 0x00,
UVC_CTRL_SU_INPUT_SELECT_CONTROL = 0x01,
} usbh_uvc_ctrl_vc_selectorunit_controls_t;
typedef enum {
UVC_CTRL_CT_CONTROL_UNDEFINED = 0x00,
UVC_CTRL_CT_SCANNING_MODE_CONTROL = 0x01,
UVC_CTRL_CT_AE_MODE_CONTROL = 0x02,
UVC_CTRL_CT_AE_PRIORITY_CONTROL = 0x03,
UVC_CTRL_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL = 0x04,
UVC_CTRL_CT_EXPOSURE_TIME_RELATIVE_CONTROL = 0x05,
UVC_CTRL_CT_FOCUS_ABSOLUTE_CONTROL = 0x06,
UVC_CTRL_CT_FOCUS_RELATIVE_CONTROL = 0x07,
UVC_CTRL_CT_FOCUS_AUTO_CONTROL = 0x08,
UVC_CTRL_CT_IRIS_ABSOLUTE_CONTROL = 0x09,
UVC_CTRL_CT_IRIS_RELATIVE_CONTROL = 0x0A,
UVC_CTRL_CT_ZOOM_ABSOLUTE_CONTROL = 0x0B,
UVC_CTRL_CT_ZOOM_RELATIVE_CONTROL = 0x0C,
UVC_CTRL_CT_PANTILT_ABSOLUTE_CONTROL = 0x0D,
UVC_CTRL_CT_PANTILT_RELATIVE_CONTROL = 0x0E,
UVC_CTRL_CT_ROLL_ABSOLUTE_CONTROL = 0x0F,
UVC_CTRL_CT_ROLL_RELATIVE_CONTROL = 0x10,
UVC_CTRL_CT_PRIVACY_CONTROL = 0x11
} usbh_uvc_ctrl_vc_cameraterminal_controls_t;
typedef enum {
UVC_CTRL_PU_CONTROL_UNDEFINED = 0x00,
UVC_CTRL_PU_BACKLIGHT_COMPENSATION_CONTROL = 0x01,
UVC_CTRL_PU_BRIGHTNESS_CONTROL = 0x02,
UVC_CTRL_PU_CONTRAST_CONTROL = 0x03,
UVC_CTRL_PU_GAIN_CONTROL = 0x04,
UVC_CTRL_PU_POWER_LINE_FREQUENCY_CONTROL = 0x05,
UVC_CTRL_PU_HUE_CONTROL = 0x06,
UVC_CTRL_PU_SATURATION_CONTROL = 0x07,
UVC_CTRL_PU_SHARPNESS_CONTROL = 0x08,
UVC_CTRL_PU_GAMMA_CONTROL = 0x09,
UVC_CTRL_PU_WHITE_BALANCE_TEMPERATURE_CONTROL = 0x0A,
UVC_CTRL_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL = 0x0B,
UVC_CTRL_PU_WHITE_BALANCE_COMPONENT_CONTROL = 0x0C,
UVC_CTRL_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL = 0x0D,
UVC_CTRL_PU_DIGITAL_MULTIPLIER_CONTROL = 0x0E,
UVC_CTRL_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL = 0x0F,
UVC_CTRL_PU_HUE_AUTO_CONTROL = 0x10,
UVC_CTRL_PU_ANALOG_VIDEO_STANDARD_CONTROL = 0x11,
UVC_CTRL_PU_ANALOG_LOCK_STATUS_CONTROL = 0x12,
} usbh_uvc_ctrl_vc_processingunit_controls_t;
typedef enum {
UVC_CTRL_VS_CONTROL_UNDEFINED = 0x00,
UVC_CTRL_VS_PROBE_CONTROL = 0x01,
UVC_CTRL_VS_COMMIT_CONTROL = 0x02,
UVC_CTRL_VS_STILL_PROBE_CONTROL = 0x03,
UVC_CTRL_VS_STILL_COMMIT_CONTROL = 0x04,
UVC_CTRL_VS_STILL_IMAGE_TRIGGER_CONTROL = 0x05,
UVC_CTRL_VS_STREAM_ERROR_CODE_CONTROL = 0x06,
UVC_CTRL_VS_GENERATE_KEY_FRAME_CONTROL = 0x07,
UVC_CTRL_VS_UPDATE_FRAME_SEGMENT_CONTROL = 0x08,
UVC_CTRL_VS_SYNCH_DELAY_CONTROL = 0x09
} usbh_uvc_ctrl_vs_interface_controls_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
uint8_t bmFlags;
uint8_t bDefaultFrameIndex;
uint8_t bAspectRatioX;
uint8_t bAspectRatioY;
uint8_t bmInterfaceFlags;
uint8_t bCopyProtect;
} __attribute__((__packed__)) usbh_uvc_format_mjpeg_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
uint32_t dwMinBitRate;
uint32_t dwMaxBitRate;
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval[0];
} __attribute__((__packed__)) usbh_uvc_frame_mjpeg_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFrameIndex;
uint8_t bmCapabilities;
uint16_t wWidth;
uint16_t wHeight;
uint32_t dwMinBitRate;
uint32_t dwMaxBitRate;
uint32_t dwMaxVideoFrameBufferSize;
uint32_t dwDefaultFrameInterval;
uint8_t bFrameIntervalType;
uint32_t dwFrameInterval[0];
} __attribute__((__packed__)) usbh_uvc_frame_uncompressed_t;
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDescriptorSubType;
uint8_t bFormatIndex;
uint8_t bNumFrameDescriptors;
uint8_t guidFormat[16];
uint8_t bBitsPerPixel;
uint8_t bDefaultFrameIndex;
uint8_t bAspectRatioX;
uint8_t bAspectRatioY;
uint8_t bmInterfaceFlags;
uint8_t bCopyProtect;
} __attribute__((__packed__)) usbh_uvc_format_uncompressed;
typedef struct {
uint16_t bmHint;
uint8_t bFormatIndex;
uint8_t bFrameIndex;
uint32_t dwFrameInterval;
uint16_t wKeyFrameRate;
uint16_t wPFrameRate;
uint16_t wCompQuality;
uint16_t wCompWindowSize;
uint16_t wDelay;
uint32_t dwMaxVideoFrameSize;
uint32_t dwMaxPayloadTransferSize;
// uint32_t dwClockFrequency;
// uint8_t bmFramingInfo;
// uint8_t bPreferedVersion;
// uint8_t bMinVersion;
// uint8_t bMaxVersion;
} __attribute__((__packed__)) usbh_uvc_ctrl_vs_probecommit_data_t;
/* D0: Frame ID.
* For frame-based formats, this bit toggles between 0 and 1 every time a new video frame begins.
* For stream-based formats, this bit toggles between 0 and 1 at the start of each new codec-specific
* segment. This behavior is required for frame-based payload formats (e.g., DV) and is optional
* for stream-based payload formats (e.g., MPEG-2 TS). For stream-based formats, support for this
* bit must be indicated via the bmFramingInfofield of the Video Probe and Commitcontrols
* (see section 4.3.1.1, Video Probe and Commit Controls).
*
* D1: End of Frame.
* This bit is set if the following payload data marks the end of the current video or still image
* frame (for framebased formats), or to indicate the end of a codec-specific segment
* (for stream-based formats). This behavior is optional for all payload formats.
* For stream-based formats, support for this bit must be indicated via the bmFramingInfofield
* of the Video Probe and CommitControls (see section 4.3.1.1, Video Probe and Commit Controls).
*
* D2: Presentation Time.
* This bit is set if the dwPresentationTimefield is being sent as part of the header.
*
* D3: Source Clock Reference
* This bit is set if the dwSourceClockfield is being sent as part of the header.
*
* D4: Reserved
*
* D5: Still Image
* This bit is set ifthe following data is part of a still image frame, and is only used for
* methods 2 and 3 of still image capture.
*
* D6: Error
* This bit is set ifthere was an error in the video or still image transmission
* for this payload. The StreamError Code control would reflect the cause of the error.
*
* D7: End of header
* This bit is set if this is the last header group in the packet, where the
* header group refers to this field and any optional fields identified by the bits in this
* field (Defined for future extension)
*/
#define UVC_HDR_EOH (1 << 7) /* End of header */
#define UVC_HDR_ERR (1 << 6) /* Error */
#define UVC_HDR_STILL (1 << 5) /* Still Image */
#define UVC_HDR_SCR (1 << 3) /* Source Clock Reference */
#define UVC_HDR_PT (1 << 2) /* Presentation Time */
#define UVC_HDR_EOF (1 << 1) /* End of Frame */
#define UVC_HDR_FID (1 << 0) /* Frame ID */
typedef struct USBHUVCDriver USBHUVCDriver;
#define USBHUVC_MESSAGETYPE_STATUS 1
#define USBHUVC_MESSAGETYPE_DATA 2
#define _usbhuvc_message_base_data \
uint16_t type; \
uint16_t length; \
systime_t timestamp;
typedef struct {
_usbhuvc_message_base_data
} usbhuvc_message_base_t;
typedef struct {
_usbhuvc_message_base_data
USBH_DECLARE_STRUCT_MEMBER(uint8_t data[0]);
} usbhuvc_message_data_t;
typedef struct {
_usbhuvc_message_base_data
USBH_DECLARE_STRUCT_MEMBER(uint8_t data[USBHUVC_MAX_STATUS_PACKET_SZ]);
} usbhuvc_message_status_t;
typedef enum {
USBHUVC_STATE_UNINITIALIZED = 0, //must call usbhuvcObjectInit
USBHUVC_STATE_STOP = 1, //the device is disconnected
USBHUVC_STATE_ACTIVE = 2, //the device is connected
USBHUVC_STATE_READY = 3, //the device has negotiated the parameters
USBHUVC_STATE_STREAMING = 4, //the device is streaming data
USBHUVC_STATE_BUSY = 5 //the driver is busy performing some action
} usbhuvc_state_t;
struct USBHUVCDriver {
/* inherited from abstract class driver */
_usbh_base_classdriver_data
usbhuvc_state_t state;
usbh_ep_t ep_int;
usbh_ep_t ep_iso;
usbh_urb_t urb_iso;
usbh_urb_t urb_int;
if_iterator_t ivc;
if_iterator_t ivs;
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc);
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc_min);
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc_max);
mailbox_t mb;
msg_t mb_buff[HAL_USBHUVC_MAX_MAILBOX_SZ];
memory_pool_t mp_data;
void *mp_data_buffer;
memory_pool_t mp_status;
usbhuvc_message_status_t mp_status_buffer[HAL_USBHUVC_STATUS_PACKETS_COUNT];
mutex_t mtx;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES];
#ifdef __cplusplus
extern "C" {
#endif
void usbhuvcObjectInit(USBHUVCDriver *uvcd);
static inline usbhuvc_state_t usbhuvcGetState(USBHUVCDriver *uvcd) {
return uvcd->state;
}
bool usbhuvcVCRequest(USBHUVCDriver *uvcdp,
uint8_t bRequest, uint8_t entity, uint8_t control,
uint16_t wLength, uint8_t *data);
bool usbhuvcVSRequest(USBHUVCDriver *uvcdp,
uint8_t bRequest, uint8_t control,
uint16_t wLength, uint8_t *data);
bool usbhuvcFindVSDescriptor(USBHUVCDriver *uvcdp,
generic_iterator_t *ics,
uint8_t bDescriptorSubtype,
bool start);
uint32_t usbhuvcEstimateRequiredEPSize(USBHUVCDriver *uvcdp, const uint8_t *formatdesc,
const uint8_t *framedesc, uint32_t dwFrameInterval);
#if USBH_DEBUG_ENABLE && USBHUVC_DEBUG_ENABLE_INFO
void usbhuvcPrintProbeCommit(const usbh_uvc_ctrl_vs_probecommit_data_t *pc);
#else
# define usbhuvcPrintProbeCommit(pc) do {} while(0)
#endif
bool usbhuvcProbe(USBHUVCDriver *uvcdp);
bool usbhuvcCommit(USBHUVCDriver *uvcdp);
void usbhuvcResetPC(USBHUVCDriver *uvcdp);
static inline const usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPCMin(USBHUVCDriver *uvcdp) {
return &uvcdp->pc_min;
}
static inline const usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPCMax(USBHUVCDriver *uvcdp) {
return &uvcdp->pc_min;
}
static inline usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPC(USBHUVCDriver *uvcdp) {
return &uvcdp->pc;
}
bool usbhuvcStreamStart(USBHUVCDriver *uvcdp, uint16_t min_ep_sz);
bool usbhuvcStreamStop(USBHUVCDriver *uvcdp);
static inline msg_t usbhuvcLockAndFetchS(USBHUVCDriver *uvcdp, msg_t *msg, systime_t timeout) {
chMtxLockS(&uvcdp->mtx);
msg_t ret = chMBFetchS(&uvcdp->mb, msg, timeout);
if (ret != MSG_OK)
chMtxUnlockS(&uvcdp->mtx);
return ret;
}
static inline msg_t usbhuvcLockAndFetch(USBHUVCDriver *uvcdp, msg_t *msg, systime_t timeout) {
osalSysLock();
msg_t ret = usbhuvcLockAndFetchS(uvcdp, msg, timeout);
osalSysUnlock();
return ret;
}
static inline void usbhuvcUnlock(USBHUVCDriver *uvcdp) {
chMtxUnlock(&uvcdp->mtx);
}
static inline void usbhuvcFreeDataMessage(USBHUVCDriver *uvcdp, usbhuvc_message_data_t *msg) {
chPoolFree(&uvcdp->mp_data, msg);
}
static inline void usbhuvcFreeStatusMessage(USBHUVCDriver *uvcdp, usbhuvc_message_status_t *msg) {
chPoolFree(&uvcdp->mp_status, msg);
}
/* global initializer */
void usbhuvcInit(void);
#ifdef __cplusplus
}
#endif
#endif
#endif /* USBH_INCLUDE_USBH_UVC_H_ */

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -29,9 +29,15 @@
#if HAL_USBH_USE_FTDI
extern const usbh_classdriverinfo_t usbhftdiClassDriverInfo;
#endif
#if HAL_USBH_USE_AOA
extern const usbh_classdriverinfo_t usbhaoaClassDriverInfo;
#endif
#if HAL_USBH_USE_MSD
extern const usbh_classdriverinfo_t usbhmsdClassDriverInfo;
#endif
#if HAL_USBH_USE_HID
extern const usbh_classdriverinfo_t usbhhidClassDriverInfo;
#endif
#if HAL_USBH_USE_UVC
extern const usbh_classdriverinfo_t usbhuvcClassDriverInfo;
#endif
@ -49,29 +55,17 @@ bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status);
void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status);
#define USBH_CLASSIN(type, req, value, index) \
(USBH_REQTYPE_IN | type | USBH_REQTYPE_CLASS), \
req, \
value, \
index
#define USBH_REQTYPE_CLASSIN(type) \
(USBH_REQTYPE_DIR_IN | type | USBH_REQTYPE_TYPE_CLASS)
#define USBH_CLASSOUT(type, req, value, index) \
(USBH_REQTYPE_OUT | type | USBH_REQTYPE_CLASS), \
req, \
value, \
index
#define USBH_REQTYPE_CLASSOUT(type) \
(USBH_REQTYPE_DIR_OUT | type | USBH_REQTYPE_TYPE_CLASS)
#define USBH_STANDARDIN(type, req, value, index) \
(USBH_REQTYPE_IN | type | USBH_REQTYPE_STANDARD), \
req, \
value, \
index
#define USBH_REQTYPE_STANDARDIN(type) \
(USBH_REQTYPE_DIR_IN | type | USBH_REQTYPE_TYPE_STANDARD)
#define USBH_STANDARDOUT(type, req, value, index) \
(USBH_REQTYPE_OUT | type | USBH_REQTYPE_STANDARD), \
req, \
value, \
index
#define USBH_REQTYPE_STANDARDOUT(type) \
(USBH_REQTYPE_DIR_OUT | type | USBH_REQTYPE_TYPE_STANDARD)
#define USBH_PID_DATA0 0
@ -82,19 +76,19 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status);
/* GetBusState and SetHubDescriptor are optional, omitted */
#define ClearHubFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
#define ClearHubFeature (((USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE) << 8) \
| USBH_REQ_CLEAR_FEATURE)
#define SetHubFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
#define SetHubFeature (((USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE) << 8) \
| USBH_REQ_SET_FEATURE)
#define ClearPortFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
#define ClearPortFeature (((USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER) << 8) \
| USBH_REQ_CLEAR_FEATURE)
#define SetPortFeature (((USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
#define SetPortFeature (((USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER) << 8) \
| USBH_REQ_SET_FEATURE)
#define GetHubDescriptor (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
#define GetHubDescriptor (((USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE) << 8) \
| USBH_REQ_GET_DESCRIPTOR)
#define GetHubStatus (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE) << 8) \
#define GetHubStatus (((USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE) << 8) \
| USBH_REQ_GET_STATUS)
#define GetPortStatus (((USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER) << 8) \
#define GetPortStatus (((USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER) << 8) \
| USBH_REQ_GET_STATUS)

View File

@ -7,11 +7,8 @@
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ((type *)(void *)((char *)(ptr) - offsetof(type, member)))
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
#define container_of(ptr, type, member) ((type *)(void *)((char *)(ptr) - offsetof(type, member)))
#endif
/*

View File

@ -1,934 +0,0 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_stm32_otg.h
* @brief STM32 OTG registers layout header.
*
* @addtogroup USB
* @{
*/
#ifndef HAL_STM32_OTG_H
#define HAL_STM32_OTG_H
/**
* @brief Number of the implemented endpoints in OTG_FS.
* @details This value does not include the endpoint 0 that is always present.
*/
#define STM32_OTG1_ENDOPOINTS_NUMBER 3
/**
* @brief Number of the implemented endpoints in OTG_HS.
* @details This value does not include the endpoint 0 that is always present.
*/
#define STM32_OTG2_ENDOPOINTS_NUMBER 5
/**
* @brief OTG_FS FIFO memory size in words.
*/
#define STM32_OTG1_FIFO_MEM_SIZE 320
/**
* @brief OTG_HS FIFO memory size in words.
*/
#define STM32_OTG2_FIFO_MEM_SIZE 1024
/**
* @brief Host channel registers group.
*/
typedef struct {
volatile uint32_t HCCHAR; /**< @brief Host channel characteristics
register. */
volatile uint32_t resvd8;
volatile uint32_t HCINT; /**< @brief Host channel interrupt register.*/
volatile uint32_t HCINTMSK; /**< @brief Host channel interrupt mask
register. */
volatile uint32_t HCTSIZ; /**< @brief Host channel transfer size
register. */
volatile uint32_t resvd14;
volatile uint32_t resvd18;
volatile uint32_t resvd1c;
} stm32_otg_host_chn_t;
/**
* @brief Device input endpoint registers group.
*/
typedef struct {
volatile uint32_t DIEPCTL; /**< @brief Device control IN endpoint
control register. */
volatile uint32_t resvd4;
volatile uint32_t DIEPINT; /**< @brief Device IN endpoint interrupt
register. */
volatile uint32_t resvdC;
volatile uint32_t DIEPTSIZ; /**< @brief Device IN endpoint transfer size
register. */
volatile uint32_t resvd14;
volatile uint32_t DTXFSTS; /**< @brief Device IN endpoint transmit FIFO
status register. */
volatile uint32_t resvd1C;
} stm32_otg_in_ep_t;
/**
* @brief Device output endpoint registers group.
*/
typedef struct {
volatile uint32_t DOEPCTL; /**< @brief Device control OUT endpoint
control register. */
volatile uint32_t resvd4;
volatile uint32_t DOEPINT; /**< @brief Device OUT endpoint interrupt
register. */
volatile uint32_t resvdC;
volatile uint32_t DOEPTSIZ; /**< @brief Device OUT endpoint transfer
size register. */
volatile uint32_t resvd14;
volatile uint32_t resvd18;
volatile uint32_t resvd1C;
} stm32_otg_out_ep_t;
/**
* @brief USB registers memory map.
*/
typedef struct {
volatile uint32_t GOTGCTL; /**< @brief OTG control and status register.*/
volatile uint32_t GOTGINT; /**< @brief OTG interrupt register. */
volatile uint32_t GAHBCFG; /**< @brief AHB configuration register. */
volatile uint32_t GUSBCFG; /**< @brief USB configuration register. */
volatile uint32_t GRSTCTL; /**< @brief Reset register size. */
volatile uint32_t GINTSTS; /**< @brief Interrupt register. */
volatile uint32_t GINTMSK; /**< @brief Interrupt mask register. */
volatile uint32_t GRXSTSR; /**< @brief Receive status debug read
register. */
volatile uint32_t GRXSTSP; /**< @brief Receive status read/pop
register. */
volatile uint32_t GRXFSIZ; /**< @brief Receive FIFO size register. */
volatile uint32_t DIEPTXF0; /**< @brief Endpoint 0 transmit FIFO size
register. */
volatile uint32_t HNPTXSTS; /**< @brief Non-periodic transmit FIFO/queue
status register. */
volatile uint32_t resvd30;
volatile uint32_t resvd34;
volatile uint32_t GCCFG; /**< @brief General core configuration. */
volatile uint32_t CID; /**< @brief Core ID register. */
volatile uint32_t resvd58[48];
volatile uint32_t HPTXFSIZ; /**< @brief Host periodic transmit FIFO size
register. */
volatile uint32_t DIEPTXF[15];/**< @brief Device IN endpoint transmit FIFO
size registers. */
volatile uint32_t resvd140[176];
volatile uint32_t HCFG; /**< @brief Host configuration register. */
volatile uint32_t HFIR; /**< @brief Host frame interval register. */
volatile uint32_t HFNUM; /**< @brief Host frame number/frame time
Remaining register. */
volatile uint32_t resvd40C;
volatile uint32_t HPTXSTS; /**< @brief Host periodic transmit FIFO/queue
status register. */
volatile uint32_t HAINT; /**< @brief Host all channels interrupt
register. */
volatile uint32_t HAINTMSK; /**< @brief Host all channels interrupt mask
register. */
volatile uint32_t resvd41C[9];
volatile uint32_t HPRT; /**< @brief Host port control and status
register. */
volatile uint32_t resvd444[47];
stm32_otg_host_chn_t hc[16]; /**< @brief Host channels array. */
volatile uint32_t resvd700[64];
volatile uint32_t DCFG; /**< @brief Device configuration register. */
volatile uint32_t DCTL; /**< @brief Device control register. */
volatile uint32_t DSTS; /**< @brief Device status register. */
volatile uint32_t resvd80C;
volatile uint32_t DIEPMSK; /**< @brief Device IN endpoint common
interrupt mask register. */
volatile uint32_t DOEPMSK; /**< @brief Device OUT endpoint common
interrupt mask register. */
volatile uint32_t DAINT; /**< @brief Device all endpoints interrupt
register. */
volatile uint32_t DAINTMSK; /**< @brief Device all endpoints interrupt
mask register. */
volatile uint32_t resvd820;
volatile uint32_t resvd824;
volatile uint32_t DVBUSDIS; /**< @brief Device VBUS discharge time
register. */
volatile uint32_t DVBUSPULSE; /**< @brief Device VBUS pulsing time
register. */
volatile uint32_t resvd830;
volatile uint32_t DIEPEMPMSK; /**< @brief Device IN endpoint FIFO empty
interrupt mask register. */
volatile uint32_t resvd838;
volatile uint32_t resvd83C;
volatile uint32_t resvd840[16];
volatile uint32_t resvd880[16];
volatile uint32_t resvd8C0[16];
stm32_otg_in_ep_t ie[16]; /**< @brief Input endpoints. */
stm32_otg_out_ep_t oe[16]; /**< @brief Output endpoints. */
volatile uint32_t resvdD00[64];
volatile uint32_t PCGCCTL; /**< @brief Power and clock gating control
register. */
volatile uint32_t resvdE04[127];
volatile uint32_t FIFO[16][1024];
} stm32_otg_t;
/**
* @name GOTGCTL register bit definitions
* @{
*/
#define GOTGCTL_BSVLD (1U<<19) /**< B-Session Valid. */
#define GOTGCTL_ASVLD (1U<<18) /**< A-Session Valid. */
#define GOTGCTL_DBCT (1U<<17) /**< Long/Short debounce time. */
#define GOTGCTL_CIDSTS (1U<<16) /**< Connector ID status. */
#define GOTGCTL_EHEN (1U<<12)
#define GOTGCTL_DHNPEN (1U<<11) /**< Device HNP enabled. */
#define GOTGCTL_HSHNPEN (1U<<10) /**< Host Set HNP enable. */
#define GOTGCTL_HNPRQ (1U<<9) /**< HNP request. */
#define GOTGCTL_HNGSCS (1U<<8) /**< Host negotiation success. */
#define GOTGCTL_BVALOVAL (1U<<7)
#define GOTGCTL_BVALOEN (1U<<6)
#define GOTGCTL_AVALOVAL (1U<<5)
#define GOTGCTL_AVALOEN (1U<<4)
#define GOTGCTL_VBVALOVAL (1U<<3)
#define GOTGCTL_VBVALOEN (1U<<2)
#define GOTGCTL_SRQ (1U<<1) /**< Session request. */
#define GOTGCTL_SRQSCS (1U<<0) /**< Session request success. */
/** @} */
/**
* @name GOTGINT register bit definitions
* @{
*/
#define GOTGINT_DBCDNE (1U<<19) /**< Debounce done. */
#define GOTGINT_ADTOCHG (1U<<18) /**< A-Device timeout change. */
#define GOTGINT_HNGDET (1U<<17) /**< Host negotiation detected. */
#define GOTGINT_HNSSCHG (1U<<9) /**< Host negotiation success
status change. */
#define GOTGINT_SRSSCHG (1U<<8) /**< Session request success
status change. */
#define GOTGINT_SEDET (1U<<2) /**< Session end detected. */
/** @} */
/**
* @name GAHBCFG register bit definitions
* @{
*/
#define GAHBCFG_PTXFELVL (1U<<8) /**< Periodic TxFIFO empty
level. */
#define GAHBCFG_TXFELVL (1U<<7) /**< Non-periodic TxFIFO empty
level. */
#define GAHBCFG_DMAEN (1U<<5) /**< DMA enable (HS only). */
#define GAHBCFG_HBSTLEN_MASK (15U<<1) /**< Burst length/type mask (HS
only). */
#define GAHBCFG_HBSTLEN(n) ((n)<<1) /**< Burst length/type (HS
only). */
#define GAHBCFG_GINTMSK (1U<<0) /**< Global interrupt mask. */
/** @} */
/**
* @name GUSBCFG register bit definitions
* @{
*/
#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */
#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */
#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */
#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field
mask. */
#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field
value. */
#define GUSBCFG_HNPCAP (1U<<9) /**< HNP-Capable. */
#define GUSBCFG_SRPCAP (1U<<8) /**< SRP-Capable. */
#define GUSBCFG_PHYSEL (1U<<6) /**< USB 2.0 High-Speed PHY or
USB 1.1 Full-Speed serial
transceiver Select. */
#define GUSBCFG_TOCAL_MASK (7U<<0) /**< HS/FS timeout calibration
field mask. */
#define GUSBCFG_TOCAL(n) ((n)<<0) /**< HS/FS timeout calibration
field value. */
/** @} */
/**
* @name GRSTCTL register bit definitions
* @{
*/
#define GRSTCTL_AHBIDL (1U<<31) /**< AHB Master Idle. */
#define GRSTCTL_TXFNUM_MASK (31U<<6) /**< TxFIFO number field mask. */
#define GRSTCTL_TXFNUM(n) ((n)<<6) /**< TxFIFO number field value. */
#define GRSTCTL_TXFFLSH (1U<<5) /**< TxFIFO flush. */
#define GRSTCTL_RXFFLSH (1U<<4) /**< RxFIFO flush. */
#define GRSTCTL_FCRST (1U<<2) /**< Host frame counter reset. */
#define GRSTCTL_HSRST (1U<<1) /**< HClk soft reset. */
#define GRSTCTL_CSRST (1U<<0) /**< Core soft reset. */
/** @} */
/**
* @name GINTSTS register bit definitions
* @{
*/
#define GINTSTS_WKUPINT (1U<<31) /**< Resume/Remote wakeup
detected interrupt. */
#define GINTSTS_SRQINT (1U<<30) /**< Session request/New session
detected interrupt. */
#define GINTSTS_DISCINT (1U<<29) /**< Disconnect detected
interrupt. */
#define GINTSTS_CIDSCHG (1U<<28) /**< Connector ID status change.*/
#define GINTSTS_PTXFE (1U<<26) /**< Periodic TxFIFO empty. */
#define GINTSTS_HCINT (1U<<25) /**< Host channels interrupt. */
#define GINTSTS_HPRTINT (1U<<24) /**< Host port interrupt. */
#define GINTSTS_IPXFR (1U<<21) /**< Incomplete periodic
transfer. */
#define GINTSTS_IISOOXFR (1U<<21) /**< Incomplete isochronous OUT
transfer. */
#define GINTSTS_IISOIXFR (1U<<20) /**< Incomplete isochronous IN
transfer. */
#define GINTSTS_OEPINT (1U<<19) /**< OUT endpoints interrupt. */
#define GINTSTS_IEPINT (1U<<18) /**< IN endpoints interrupt. */
#define GINTSTS_EOPF (1U<<15) /**< End of periodic frame
interrupt. */
#define GINTSTS_ISOODRP (1U<<14) /**< Isochronous OUT packet
dropped interrupt. */
#define GINTSTS_ENUMDNE (1U<<13) /**< Enumeration done. */
#define GINTSTS_USBRST (1U<<12) /**< USB reset. */
#define GINTSTS_USBSUSP (1U<<11) /**< USB suspend. */
#define GINTSTS_ESUSP (1U<<10) /**< Early suspend. */
#define GINTSTS_GONAKEFF (1U<<7) /**< Global OUT NAK effective. */
#define GINTSTS_GINAKEFF (1U<<6) /**< Global IN non-periodic NAK
effective. */
#define GINTSTS_NPTXFE (1U<<5) /**< Non-periodic TxFIFO empty. */
#define GINTSTS_RXFLVL (1U<<4) /**< RxFIFO non-empty. */
#define GINTSTS_SOF (1U<<3) /**< Start of frame. */
#define GINTSTS_OTGINT (1U<<2) /**< OTG interrupt. */
#define GINTSTS_MMIS (1U<<1) /**< Mode Mismatch interrupt. */
#define GINTSTS_CMOD (1U<<0) /**< Current mode of operation. */
/** @} */
/**
* @name GINTMSK register bit definitions
* @{
*/
#define GINTMSK_WKUM (1U<<31) /**< Resume/remote wakeup
detected interrupt mask. */
#define GINTMSK_SRQM (1U<<30) /**< Session request/New session
detected interrupt mask. */
#define GINTMSK_DISCM (1U<<29) /**< Disconnect detected
interrupt mask. */
#define GINTMSK_CIDSCHGM (1U<<28) /**< Connector ID status change
mask. */
#define GINTMSK_PTXFEM (1U<<26) /**< Periodic TxFIFO empty mask.*/
#define GINTMSK_HCM (1U<<25) /**< Host channels interrupt
mask. */
#define GINTMSK_HPRTM (1U<<24) /**< Host port interrupt mask. */
#define GINTMSK_IPXFRM (1U<<21) /**< Incomplete periodic
transfer mask. */
#define GINTMSK_IISOOXFRM (1U<<21) /**< Incomplete isochronous OUT
transfer mask. */
#define GINTMSK_IISOIXFRM (1U<<20) /**< Incomplete isochronous IN
transfer mask. */
#define GINTMSK_OEPM (1U<<19) /**< OUT endpoints interrupt
mask. */
#define GINTMSK_IEPM (1U<<18) /**< IN endpoints interrupt
mask. */
#define GINTMSK_EOPFM (1U<<15) /**< End of periodic frame
interrupt mask. */
#define GINTMSK_ISOODRPM (1U<<14) /**< Isochronous OUT packet
dropped interrupt mask. */
#define GINTMSK_ENUMDNEM (1U<<13) /**< Enumeration done mask. */
#define GINTMSK_USBRSTM (1U<<12) /**< USB reset mask. */
#define GINTMSK_USBSUSPM (1U<<11) /**< USB suspend mask. */
#define GINTMSK_ESUSPM (1U<<10) /**< Early suspend mask. */
#define GINTMSK_GONAKEFFM (1U<<7) /**< Global OUT NAK effective
mask. */
#define GINTMSK_GINAKEFFM (1U<<6) /**< Global non-periodic IN NAK
effective mask. */
#define GINTMSK_NPTXFEM (1U<<5) /**< Non-periodic TxFIFO empty
mask. */
#define GINTMSK_RXFLVLM (1U<<4) /**< Receive FIFO non-empty
mask. */
#define GINTMSK_SOFM (1U<<3) /**< Start of (micro)frame mask.*/
#define GINTMSK_OTGM (1U<<2) /**< OTG interrupt mask. */
#define GINTMSK_MMISM (1U<<1) /**< Mode Mismatch interrupt
mask. */
/** @} */
/**
* @name GRXSTSR register bit definitions
* @{
*/
#define GRXSTSR_PKTSTS_MASK (15U<<17) /**< Packet status mask. */
#define GRXSTSR_PKTSTS(n) ((n)<<17) /**< Packet status value. */
#define GRXSTSR_OUT_GLOBAL_NAK GRXSTSR_PKTSTS(1)
#define GRXSTSR_OUT_DATA GRXSTSR_PKTSTS(2)
#define GRXSTSR_OUT_COMP GRXSTSR_PKTSTS(3)
#define GRXSTSR_SETUP_COMP GRXSTSR_PKTSTS(4)
#define GRXSTSR_SETUP_DATA GRXSTSR_PKTSTS(6)
#define GRXSTSR_DPID_MASK (3U<<15) /**< Data PID mask. */
#define GRXSTSR_DPID(n) ((n)<<15) /**< Data PID value. */
#define GRXSTSR_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
#define GRXSTSR_BCNT(n) ((n)<<4) /**< Byte count value. */
#define GRXSTSR_CHNUM_MASK (15U<<0) /**< Channel number mask. */
#define GRXSTSR_CHNUM(n) ((n)<<0) /**< Channel number value. */
#define GRXSTSR_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
#define GRXSTSR_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
/** @} */
/**
* @name GRXSTSP register bit definitions
* @{
*/
#define GRXSTSP_PKTSTS_MASK (15<<17) /**< Packet status mask. */
#define GRXSTSP_PKTSTS(n) ((n)<<17) /**< Packet status value. */
#define GRXSTSP_OUT_GLOBAL_NAK GRXSTSP_PKTSTS(1)
#define GRXSTSP_OUT_DATA GRXSTSP_PKTSTS(2)
#define GRXSTSP_OUT_COMP GRXSTSP_PKTSTS(3)
#define GRXSTSP_SETUP_COMP GRXSTSP_PKTSTS(4)
#define GRXSTSP_SETUP_DATA GRXSTSP_PKTSTS(6)
#define GRXSTSP_DPID_MASK (3U<<15) /**< Data PID mask. */
#define GRXSTSP_DPID(n) ((n)<<15) /**< Data PID value. */
#define GRXSTSP_BCNT_MASK (0x7FF<<4) /**< Byte count mask. */
#define GRXSTSP_BCNT_OFF 4 /**< Byte count offset. */
#define GRXSTSP_BCNT(n) ((n)<<4) /**< Byte count value. */
#define GRXSTSP_CHNUM_MASK (15U<<0) /**< Channel number mask. */
#define GRXSTSP_CHNUM(n) ((n)<<0) /**< Channel number value. */
#define GRXSTSP_EPNUM_MASK (15U<<0) /**< Endpoint number mask. */
#define GRXSTSP_EPNUM_OFF 0 /**< Endpoint number offset. */
#define GRXSTSP_EPNUM(n) ((n)<<0) /**< Endpoint number value. */
/** @} */
/**
* @name GRXFSIZ register bit definitions
* @{
*/
#define GRXFSIZ_RXFD_MASK (0xFFFF<<0) /**< RxFIFO depth mask. */
#define GRXFSIZ_RXFD(n) ((n)<<0) /**< RxFIFO depth value. */
/** @} */
/**
* @name DIEPTXFx register bit definitions
* @{
*/
#define DIEPTXF_INEPTXFD_MASK (0xFFFFU<<16)/**< IN endpoint TxFIFO depth
mask. */
#define DIEPTXF_INEPTXFD(n) ((n)<<16) /**< IN endpoint TxFIFO depth
value. */
#define DIEPTXF_INEPTXSA_MASK (0xFFFF<<0) /**< IN endpoint FIFOx transmit
RAM start address mask. */
#define DIEPTXF_INEPTXSA(n) ((n)<<0) /**< IN endpoint FIFOx transmit
RAM start address value. */
/** @} */
/**
* @name GCCFG register bit definitions
* @{
*/
/* Definitions for stepping 1.*/
#define GCCFG_NOVBUSSENS (1U<<21) /**< VBUS sensing disable. */
#define GCCFG_SOFOUTEN (1U<<20) /**< SOF output enable. */
#define GCCFG_VBUSBSEN (1U<<19) /**< Enable the VBUS sensing "B"
device. */
#define GCCFG_VBUSASEN (1U<<18) /**< Enable the VBUS sensing "A"
device. */
/* Definitions for stepping 2.*/
#define GCCFG_VBDEN (1U<<21) /**< VBUS sensing enable. */
#define GCCFG_PWRDWN (1U<<16) /**< Power down. */
/** @} */
/**
* @name HPTXFSIZ register bit definitions
* @{
*/
#define HPTXFSIZ_PTXFD_MASK (0xFFFFU<<16)/**< Host periodic TxFIFO
depth mask. */
#define HPTXFSIZ_PTXFD(n) ((n)<<16) /**< Host periodic TxFIFO
depth value. */
#define HPTXFSIZ_PTXSA_MASK (0xFFFFU<<0)/**< Host periodic TxFIFO
Start address mask. */
#define HPTXFSIZ_PTXSA(n) ((n)<<0) /**< Host periodic TxFIFO
start address value. */
/** @} */
/**
* @name HCFG register bit definitions
* @{
*/
#define HCFG_FSLSS (1U<<2) /**< FS- and LS-only support. */
#define HCFG_FSLSPCS_MASK (3U<<0) /**< FS/LS PHY clock select
mask. */
#define HCFG_FSLSPCS_48 (1U<<0) /**< PHY clock is running at
48 MHz. */
#define HCFG_FSLSPCS_6 (2U<<0) /**< PHY clock is running at
6 MHz. */
/** @} */
/**
* @name HFIR register bit definitions
* @{
*/
#define HFIR_FRIVL_MASK (0xFFFFU<<0)/**< Frame interval mask. */
#define HFIR_FRIVL(n) ((n)<<0) /**< Frame interval value. */
/** @} */
/**
* @name HFNUM register bit definitions
* @{
*/
#define HFNUM_FTREM_MASK (0xFFFFU<<16)/**< Frame time Remaining mask.*/
#define HFNUM_FTREM(n) ((n)<<16) /**< Frame time Remaining value.*/
#define HFNUM_FRNUM_MASK (0xFFFFU<<0)/**< Frame number mask. */
#define HFNUM_FRNUM(n) ((n)<<0) /**< Frame number value. */
/** @} */
/**
* @name HPTXSTS register bit definitions
* @{
*/
#define HPTXSTS_PTXQTOP_MASK (0xFFU<<24) /**< Top of the periodic
transmit request queue
mask. */
#define HPTXSTS_PTXQTOP(n) ((n)<<24) /**< Top of the periodic
transmit request queue
value. */
#define HPTXSTS_PTXQSAV_MASK (0xFF<<16) /**< Periodic transmit request
queue Space Available
mask. */
#define HPTXSTS_PTXQSAV(n) ((n)<<16) /**< Periodic transmit request
queue Space Available
value. */
#define HPTXSTS_PTXFSAVL_MASK (0xFFFF<<0) /**< Periodic transmit Data
FIFO Space Available
mask. */
#define HPTXSTS_PTXFSAVL(n) ((n)<<0) /**< Periodic transmit Data
FIFO Space Available
value. */
/** @} */
/**
* @name HAINT register bit definitions
* @{
*/
#define HAINT_HAINT_MASK (0xFFFFU<<0)/**< Channel interrupts mask. */
#define HAINT_HAINT(n) ((n)<<0) /**< Channel interrupts value. */
/** @} */
/**
* @name HAINTMSK register bit definitions
* @{
*/
#define HAINTMSK_HAINTM_MASK (0xFFFFU<<0)/**< Channel interrupt mask
mask. */
#define HAINTMSK_HAINTM(n) ((n)<<0) /**< Channel interrupt mask
value. */
/** @} */
/**
* @name HPRT register bit definitions
* @{
*/
#define HPRT_PSPD_MASK (3U<<17) /**< Port speed mask. */
#define HPRT_PSPD_FS (1U<<17) /**< Full speed value. */
#define HPRT_PSPD_LS (2U<<17) /**< Low speed value. */
#define HPRT_PTCTL_MASK (15<<13) /**< Port Test control mask. */
#define HPRT_PTCTL(n) ((n)<<13) /**< Port Test control value. */
#define HPRT_PPWR (1U<<12) /**< Port power. */
#define HPRT_PLSTS_MASK (3U<<11) /**< Port Line status mask. */
#define HPRT_PLSTS_DM (1U<<11) /**< Logic level of D-. */
#define HPRT_PLSTS_DP (1U<<10) /**< Logic level of D+. */
#define HPRT_PRST (1U<<8) /**< Port reset. */
#define HPRT_PSUSP (1U<<7) /**< Port suspend. */
#define HPRT_PRES (1U<<6) /**< Port Resume. */
#define HPRT_POCCHNG (1U<<5) /**< Port overcurrent change. */
#define HPRT_POCA (1U<<4) /**< Port overcurrent active. */
#define HPRT_PENCHNG (1U<<3) /**< Port enable/disable change.*/
#define HPRT_PENA (1U<<2) /**< Port enable. */
#define HPRT_PCDET (1U<<1) /**< Port Connect detected. */
#define HPRT_PCSTS (1U<<0) /**< Port connect status. */
/** @} */
/**
* @name HCCHAR register bit definitions
* @{
*/
#define HCCHAR_CHENA (1U<<31) /**< Channel enable. */
#define HCCHAR_CHDIS (1U<<30) /**< Channel Disable. */
#define HCCHAR_ODDFRM (1U<<29) /**< Odd frame. */
#define HCCHAR_DAD_MASK (0x7FU<<22) /**< Device Address mask. */
#define HCCHAR_DAD(n) ((n)<<22) /**< Device Address value. */
#define HCCHAR_MCNT_MASK (3U<<20) /**< Multicount mask. */
#define HCCHAR_MCNT(n) ((n)<<20) /**< Multicount value. */
#define HCCHAR_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
#define HCCHAR_EPTYP(n) ((n)<<18) /**< Endpoint type value. */
#define HCCHAR_EPTYP_CTL (0U<<18) /**< Control endpoint value. */
#define HCCHAR_EPTYP_ISO (1U<<18) /**< Isochronous endpoint value.*/
#define HCCHAR_EPTYP_BULK (2U<<18) /**< Bulk endpoint value. */
#define HCCHAR_EPTYP_INTR (3U<<18) /**< Interrupt endpoint value. */
#define HCCHAR_LSDEV (1U<<17) /**< Low-Speed device. */
#define HCCHAR_EPDIR (1U<<15) /**< Endpoint direction. */
#define HCCHAR_EPNUM_MASK (15U<<11) /**< Endpoint number mask. */
#define HCCHAR_EPNUM(n) ((n)<<11) /**< Endpoint number value. */
#define HCCHAR_MPS_MASK (0x7FFU<<0) /**< Maximum packet size mask. */
#define HCCHAR_MPS(n) ((n)<<0) /**< Maximum packet size value. */
/** @} */
/**
* @name HCINT register bit definitions
* @{
*/
#define HCINT_DTERR (1U<<10) /**< Data toggle error. */
#define HCINT_FRMOR (1U<<9) /**< Frame overrun. */
#define HCINT_BBERR (1U<<8) /**< Babble error. */
#define HCINT_TRERR (1U<<7) /**< Transaction Error. */
#define HCINT_ACK (1U<<5) /**< ACK response
received/transmitted
interrupt. */
#define HCINT_NAK (1U<<4) /**< NAK response received
interrupt. */
#define HCINT_STALL (1U<<3) /**< STALL response received
interrupt. */
#define HCINT_AHBERR (1U<<2) /**< AHB error interrupt. */
#define HCINT_CHH (1U<<1) /**< Channel halted. */
#define HCINT_XFRC (1U<<0) /**< Transfer completed. */
/** @} */
/**
* @name HCINTMSK register bit definitions
* @{
*/
#define HCINTMSK_DTERRM (1U<<10) /**< Data toggle error mask. */
#define HCINTMSK_FRMORM (1U<<9) /**< Frame overrun mask. */
#define HCINTMSK_BBERRM (1U<<8) /**< Babble error mask. */
#define HCINTMSK_TRERRM (1U<<7) /**< Transaction error mask. */
#define HCINTMSK_NYET (1U<<6) /**< NYET response received
interrupt mask. */
#define HCINTMSK_ACKM (1U<<5) /**< ACK Response
received/transmitted
interrupt mask. */
#define HCINTMSK_NAKM (1U<<4) /**< NAK response received
interrupt mask. */
#define HCINTMSK_STALLM (1U<<3) /**< STALL response received
interrupt mask. */
#define HCINTMSK_AHBERRM (1U<<2) /**< AHB error interrupt mask. */
#define HCINTMSK_CHHM (1U<<1) /**< Channel halted mask. */
#define HCINTMSK_XFRCM (1U<<0) /**< Transfer completed mask. */
/** @} */
/**
* @name HCTSIZ register bit definitions
* @{
*/
#define HCTSIZ_DPID_MASK (3U<<29) /**< PID mask. */
#define HCTSIZ_DPID_DATA0 (0U<<29) /**< DATA0. */
#define HCTSIZ_DPID_DATA2 (1U<<29) /**< DATA2. */
#define HCTSIZ_DPID_DATA1 (2U<<29) /**< DATA1. */
#define HCTSIZ_DPID_MDATA (3U<<29) /**< MDATA. */
#define HCTSIZ_DPID_SETUP (3U<<29) /**< SETUP. */
#define HCTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
#define HCTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define HCTSIZ_XFRSIZ_MASK (0x7FFFF<<0)/**< Transfer size mask. */
#define HCTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name DCFG register bit definitions
* @{
*/
#define DCFG_PFIVL_MASK (3U<<11) /**< Periodic frame interval
mask. */
#define DCFG_PFIVL(n) ((n)<<11) /**< Periodic frame interval
value. */
#define DCFG_DAD_MASK (0x7FU<<4) /**< Device address mask. */
#define DCFG_DAD(n) ((n)<<4) /**< Device address value. */
#define DCFG_NZLSOHSK (1U<<2) /**< Non-Zero-Length status
OUT handshake. */
#define DCFG_DSPD_MASK (3U<<0) /**< Device speed mask. */
#define DCFG_DSPD_HS (0U<<0) /**< High speed (USB 2.0). */
#define DCFG_DSPD_HS_FS (1U<<0) /**< High speed (USB 2.0) in FS
mode. */
#define DCFG_DSPD_FS11 (3U<<0) /**< Full speed (USB 1.1
transceiver clock is 48
MHz). */
/** @} */
/**
* @name DCTL register bit definitions
* @{
*/
#define DCTL_POPRGDNE (1U<<11) /**< Power-on programming done. */
#define DCTL_CGONAK (1U<<10) /**< Clear global OUT NAK. */
#define DCTL_SGONAK (1U<<9) /**< Set global OUT NAK. */
#define DCTL_CGINAK (1U<<8) /**< Clear global non-periodic
IN NAK. */
#define DCTL_SGINAK (1U<<7) /**< Set global non-periodic
IN NAK. */
#define DCTL_TCTL_MASK (7U<<4) /**< Test control mask. */
#define DCTL_TCTL(n) ((n)<<4 /**< Test control value. */
#define DCTL_GONSTS (1U<<3) /**< Global OUT NAK status. */
#define DCTL_GINSTS (1U<<2) /**< Global non-periodic IN
NAK status. */
#define DCTL_SDIS (1U<<1) /**< Soft disconnect. */
#define DCTL_RWUSIG (1U<<0) /**< Remote wakeup signaling. */
/** @} */
/**
* @name DSTS register bit definitions
* @{
*/
#define DSTS_FNSOF_MASK (0x3FFU<<8) /**< Frame number of the received
SOF mask. */
#define DSTS_FNSOF(n) ((n)<<8) /**< Frame number of the received
SOF value. */
#define DSTS_FNSOF_ODD (1U<<8) /**< Frame parity of the received
SOF value. */
#define DSTS_EERR (1U<<3) /**< Erratic error. */
#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is
running at 48 MHz). */
#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed. */
#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */
/** @} */
/**
* @name DIEPMSK register bit definitions
* @{
*/
#define DIEPMSK_TXFEM (1U<<6) /**< Transmit FIFO empty mask. */
#define DIEPMSK_INEPNEM (1U<<6) /**< IN endpoint NAK effective
mask. */
#define DIEPMSK_ITTXFEMSK (1U<<4) /**< IN token received when
TxFIFO empty mask. */
#define DIEPMSK_TOCM (1U<<3) /**< Timeout condition mask. */
#define DIEPMSK_EPDM (1U<<1) /**< Endpoint disabled
interrupt mask. */
#define DIEPMSK_XFRCM (1U<<0) /**< Transfer completed
interrupt mask. */
/** @} */
/**
* @name DOEPMSK register bit definitions
* @{
*/
#define DOEPMSK_OTEPDM (1U<<4) /**< OUT token received when
endpoint disabled mask. */
#define DOEPMSK_STUPM (1U<<3) /**< SETUP phase done mask. */
#define DOEPMSK_EPDM (1U<<1) /**< Endpoint disabled
interrupt mask. */
#define DOEPMSK_XFRCM (1U<<0) /**< Transfer completed
interrupt mask. */
/** @} */
/**
* @name DAINT register bit definitions
* @{
*/
#define DAINT_OEPINT_MASK (0xFFFFU<<16)/**< OUT endpoint interrupt
bits mask. */
#define DAINT_OEPINT(n) ((n)<<16) /**< OUT endpoint interrupt
bits value. */
#define DAINT_IEPINT_MASK (0xFFFFU<<0)/**< IN endpoint interrupt
bits mask. */
#define DAINT_IEPINT(n) ((n)<<0) /**< IN endpoint interrupt
bits value. */
/** @} */
/**
* @name DAINTMSK register bit definitions
* @{
*/
#define DAINTMSK_OEPM_MASK (0xFFFFU<<16)/**< OUT EP interrupt mask
bits mask. */
#define DAINTMSK_OEPM(n) (1U<<(16+(n)))/**< OUT EP interrupt mask
bits value. */
#define DAINTMSK_IEPM_MASK (0xFFFFU<<0)/**< IN EP interrupt mask
bits mask. */
#define DAINTMSK_IEPM(n) (1U<<(n)) /**< IN EP interrupt mask
bits value. */
/** @} */
/**
* @name DVBUSDIS register bit definitions
* @{
*/
#define DVBUSDIS_VBUSDT_MASK (0xFFFFU<<0)/**< Device VBUS discharge
time mask. */
#define DVBUSDIS_VBUSDT(n) ((n)<<0) /**< Device VBUS discharge
time value. */
/** @} */
/**
* @name DVBUSPULSE register bit definitions
* @{
*/
#define DVBUSPULSE_DVBUSP_MASK (0xFFFU<<0) /**< Device VBUSpulsing time
mask. */
#define DVBUSPULSE_DVBUSP(n) ((n)<<0) /**< Device VBUS pulsing time
value. */
/** @} */
/**
* @name DIEPEMPMSK register bit definitions
* @{
*/
#define DIEPEMPMSK_INEPTXFEM(n) (1U<<(n)) /**< IN EP Tx FIFO empty
interrupt mask bit. */
/** @} */
/**
* @name DIEPCTL register bit definitions
* @{
*/
#define DIEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
#define DIEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
#define DIEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
#define DIEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
#define DIEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
#define DIEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
#define DIEPCTL_SNAK (1U<<27) /**< Set NAK. */
#define DIEPCTL_CNAK (1U<<26) /**< Clear NAK. */
#define DIEPCTL_TXFNUM_MASK (15U<<22) /**< TxFIFO number mask. */
#define DIEPCTL_TXFNUM(n) ((n)<<22) /**< TxFIFO number value. */
#define DIEPCTL_STALL (1U<<21) /**< STALL handshake. */
#define DIEPCTL_SNPM (1U<<20) /**< Snoop mode. */
#define DIEPCTL_EPTYP_MASK (3<<18) /**< Endpoint type mask. */
#define DIEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
#define DIEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
#define DIEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
#define DIEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
#define DIEPCTL_NAKSTS (1U<<17) /**< NAK status. */
#define DIEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
#define DIEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
#define DIEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
#define DIEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
#define DIEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
/** @} */
/**
* @name DIEPINT register bit definitions
* @{
*/
#define DIEPINT_TXFE (1U<<7) /**< Transmit FIFO empty. */
#define DIEPINT_INEPNE (1U<<6) /**< IN endpoint NAK effective. */
#define DIEPINT_ITTXFE (1U<<4) /**< IN Token received when
TxFIFO is empty. */
#define DIEPINT_TOC (1U<<3) /**< Timeout condition. */
#define DIEPINT_EPDISD (1U<<1) /**< Endpoint disabled
interrupt. */
#define DIEPINT_XFRC (1U<<0) /**< Transfer completed. */
/** @} */
/**
* @name DIEPTSIZ register bit definitions
* @{
*/
#define DIEPTSIZ_MCNT_MASK (3U<<29) /**< Multi count mask. */
#define DIEPTSIZ_MCNT(n) ((n)<<29) /**< Multi count value. */
#define DIEPTSIZ_PKTCNT_MASK (0x3FF<<19) /**< Packet count mask. */
#define DIEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define DIEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
#define DIEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name DTXFSTS register bit definitions.
* @{
*/
#define DTXFSTS_INEPTFSAV_MASK (0xFFFF<<0) /**< IN endpoint TxFIFO space
available. */
/** @} */
/**
* @name DOEPCTL register bit definitions.
* @{
*/
#define DOEPCTL_EPENA (1U<<31) /**< Endpoint enable. */
#define DOEPCTL_EPDIS (1U<<30) /**< Endpoint disable. */
#define DOEPCTL_SD1PID (1U<<29) /**< Set DATA1 PID. */
#define DOEPCTL_SODDFRM (1U<<29) /**< Set odd frame. */
#define DOEPCTL_SD0PID (1U<<28) /**< Set DATA0 PID. */
#define DOEPCTL_SEVNFRM (1U<<28) /**< Set even frame. */
#define DOEPCTL_SNAK (1U<<27) /**< Set NAK. */
#define DOEPCTL_CNAK (1U<<26) /**< Clear NAK. */
#define DOEPCTL_STALL (1U<<21) /**< STALL handshake. */
#define DOEPCTL_SNPM (1U<<20) /**< Snoop mode. */
#define DOEPCTL_EPTYP_MASK (3U<<18) /**< Endpoint type mask. */
#define DOEPCTL_EPTYP_CTRL (0U<<18) /**< Control. */
#define DOEPCTL_EPTYP_ISO (1U<<18) /**< Isochronous. */
#define DOEPCTL_EPTYP_BULK (2U<<18) /**< Bulk. */
#define DOEPCTL_EPTYP_INTR (3U<<18) /**< Interrupt. */
#define DOEPCTL_NAKSTS (1U<<17) /**< NAK status. */
#define DOEPCTL_EONUM (1U<<16) /**< Even/odd frame. */
#define DOEPCTL_DPID (1U<<16) /**< Endpoint data PID. */
#define DOEPCTL_USBAEP (1U<<15) /**< USB active endpoint. */
#define DOEPCTL_MPSIZ_MASK (0x3FFU<<0) /**< Maximum Packet size mask. */
#define DOEPCTL_MPSIZ(n) ((n)<<0) /**< Maximum Packet size value. */
/** @} */
/**
* @name DOEPINT register bit definitions
* @{
*/
#define DOEPINT_B2BSTUP (1U<<6) /**< Back-to-back SETUP packets
received. */
#define DOEPINT_OTEPDIS (1U<<4) /**< OUT token received when
endpoint disabled. */
#define DOEPINT_STUP (1U<<3) /**< SETUP phase done. */
#define DOEPINT_EPDISD (1U<<1) /**< Endpoint disabled
interrupt. */
#define DOEPINT_XFRC (1U<<0) /**< Transfer completed
interrupt. */
/** @} */
/**
* @name DOEPTSIZ register bit definitions
* @{
*/
#define DOEPTSIZ_RXDPID_MASK (3U<<29) /**< Received data PID mask. */
#define DOEPTSIZ_RXDPID(n) ((n)<<29) /**< Received data PID value. */
#define DOEPTSIZ_STUPCNT_MASK (3U<<29) /**< SETUP packet count mask. */
#define DOEPTSIZ_STUPCNT(n) ((n)<<29) /**< SETUP packet count value. */
#define DOEPTSIZ_PKTCNT_MASK (0x3FFU<<19)/**< Packet count mask. */
#define DOEPTSIZ_PKTCNT(n) ((n)<<19) /**< Packet count value. */
#define DOEPTSIZ_XFRSIZ_MASK (0x7FFFFU<<0)/**< Transfer size mask. */
#define DOEPTSIZ_XFRSIZ(n) ((n)<<0) /**< Transfer size value. */
/** @} */
/**
* @name PCGCCTL register bit definitions
* @{
*/
#define PCGCCTL_PHYSUSP (1U<<4) /**< PHY Suspended. */
#define PCGCCTL_GATEHCLK (1U<<1) /**< Gate HCLK. */
#define PCGCCTL_STPPCLK (1U<<0) /**< Stop PCLK. */
/** @} */
/**
* @brief OTG_FS registers block memory address.
*/
#define OTG_FS_ADDR 0x50000000
/**
* @brief OTG_HS registers block memory address.
*/
#define OTG_HS_ADDR 0x40040000
/**
* @brief Accesses to the OTG_FS registers block.
*/
#define OTG_FS ((stm32_otg_t *)OTG_FS_ADDR)
/**
* @brief Accesses to the OTG_HS registers block.
*/
#define OTG_HS ((stm32_otg_t *)OTG_HS_ADDR)
#endif /* STM32_OTG_H */
/** @} */

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,6 +21,53 @@
#include "usbh/internal.h"
#include <string.h>
#if STM32_USBH_USE_OTG1
#if !defined(STM32_OTG1_CHANNELS_NUMBER)
#error "STM32_OTG1_CHANNELS_NUMBER must be defined"
#endif
#if !defined(STM32_OTG1_RXFIFO_SIZE)
#define STM32_OTG1_RXFIFO_SIZE 1024
#endif
#if !defined(STM32_OTG1_PTXFIFO_SIZE)
#define STM32_OTG1_PTXFIFO_SIZE 128
#endif
#if !defined(STM32_OTG1_NPTXFIFO_SIZE)
#define STM32_OTG1_NPTXFIFO_SIZE 128
#endif
#if (STM32_OTG1_RXFIFO_SIZE + STM32_OTG1_PTXFIFO_SIZE + STM32_OTG1_NPTXFIFO_SIZE) > (STM32_OTG1_FIFO_MEM_SIZE * 4)
#error "Not enough memory in OTG1 implementation"
#elif (STM32_OTG1_RXFIFO_SIZE + STM32_OTG1_PTXFIFO_SIZE + STM32_OTG1_NPTXFIFO_SIZE) < (STM32_OTG1_FIFO_MEM_SIZE * 4)
#warning "Spare memory in OTG1; could enlarge RX, PTX or NPTX FIFO sizes"
#endif
#if (STM32_OTG1_RXFIFO_SIZE % 4) || (STM32_OTG1_PTXFIFO_SIZE % 4) || (STM32_OTG1_NPTXFIFO_SIZE % 4)
#error "FIFO sizes must be a multiple of 32-bit words"
#endif
#endif
#if STM32_USBH_USE_OTG2
#if !defined(STM32_OTG2_CHANNELS_NUMBER)
#error "STM32_OTG2_CHANNELS_NUMBER must be defined"
#endif
#if !defined(STM32_OTG2_RXFIFO_SIZE)
#define STM32_OTG2_RXFIFO_SIZE 2048
#endif
#if !defined(STM32_OTG2_PTXFIFO_SIZE)
#define STM32_OTG2_PTXFIFO_SIZE 1024
#endif
#if !defined(STM32_OTG2_NPTXFIFO_SIZE)
#define STM32_OTG2_NPTXFIFO_SIZE 1024
#endif
#if (STM32_OTG2_RXFIFO_SIZE + STM32_OTG2_PTXFIFO_SIZE + STM32_OTG2_NPTXFIFO_SIZE) > (STM32_OTG2_FIFO_MEM_SIZE * 4)
#error "Not enough memory in OTG2 implementation"
#elif (STM32_OTG2_RXFIFO_SIZE + STM32_OTG2_PTXFIFO_SIZE + STM32_OTG2_NPTXFIFO_SIZE) < (STM32_OTG2_FIFO_MEM_SIZE * 4)
#warning "Spare memory in OTG2; could enlarge RX, PTX or NPTX FIFO sizes"
#endif
#if (STM32_OTG2_RXFIFO_SIZE % 4) || (STM32_OTG2_PTXFIFO_SIZE % 4) || (STM32_OTG2_NPTXFIFO_SIZE % 4)
#error "FIFO sizes must be a multiple of 32-bit words"
#endif
#endif
#if USBH_LLD_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
@ -492,7 +539,7 @@ static uint32_t _write_packet(struct list_head *list, uint32_t space_available)
void usbh_lld_ep_object_init(usbh_ep_t *ep) {
/* CTRL(IN) CTRL(OUT) INT(IN) INT(OUT) BULK(IN) BULK(OUT) ISO(IN) ISO(OUT)
* STALL si sólo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP)
* STALL si solo DAT/STAT si si si si no no ep->type != ISO && (ep->type != CTRL || ctrlphase != SETUP)
* ACK si si si si si si no no ep->type != ISO
* NAK si si si si si si no no ep->type != ISO
* BBERR si no si no si no si no ep->in
@ -563,6 +610,11 @@ void usbh_lld_ep_close(usbh_ep_t *ep) {
osalOsRescheduleS();
}
bool usbh_lld_ep_reset(usbh_ep_t *ep) {
ep->dt_mask = HCTSIZ_DPID_DATA0;
return TRUE;
}
void usbh_lld_urb_submit(usbh_urb_t *urb) {
usbh_ep_t *const ep = urb->ep;
@ -596,17 +648,20 @@ bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status) {
if (hcm->halt_reason == USBH_LLD_HALTREASON_NONE) {
/* The channel is not being halted */
uinfof("\t%s: usbh_lld_urb_abort: channel is not being halted", hcm->ep->name);
urb->status = status;
_halt_channel(ep->device->host, hcm, USBH_LLD_HALTREASON_ABORT);
} else {
/* The channel is being halted, so we can't re-halt it. The CHH interrupt will
* be in charge of completing the transfer, but the URB will not have the specified status.
*/
uinfof("\t%s: usbh_lld_urb_abort: channel is being halted", hcm->ep->name);
}
return FALSE;
}
/* This URB is active, we can cancel it now */
uinfof("\t%s: usbh_lld_urb_abort: URB is not active", hcm->ep->name);
_transfer_completedI(ep, urb, status);
return TRUE;
@ -855,8 +910,12 @@ static inline void _chh_int(USBHDriver *host, stm32_hc_management_t *hcm, stm32_
break;
case USBH_LLD_HALTREASON_STALL:
if ((ep->type == USBH_EPTYPE_CTRL) && (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_SETUP)) {
uerrf("\t%s: Faulty device: STALLed SETUP phase", ep->name);
if (ep->type == USBH_EPTYPE_CTRL) {
if (ep->xfer.u.ctrl_phase == USBH_LLD_CTRLPHASE_SETUP) {
uerrf("\t%s: Faulty device: STALLed SETUP phase", ep->name);
}
} else {
ep->status = USBH_EPSTATUS_HALTED;
}
_transfer_completed(ep, urb, USBH_URBSTATUS_STALL);
break;
@ -926,10 +985,15 @@ static inline void _hcint_int(USBHDriver *host) {
haint = host->otg->HAINT;
haint &= host->otg->HAINTMSK;
#if USBH_LLD_DEBUG_ENABLE_ERRORS
if (!haint) {
uerrf("HAINT=%08x, HAINTMSK=%08x", host->otg->HAINT, host->otg->HAINTMSK);
uint32_t a, b;
a = host->otg->HAINT;
b = host->otg->HAINTMSK;
uerrf("HAINT=%08x, HAINTMSK=%08x", a, b);
return;
}
#endif
#if 1 //channel lookup loop
uint8_t i;
@ -1186,11 +1250,17 @@ static void usb_lld_serve_interrupt(USBHDriver *host) {
}
gintsts &= otg->GINTMSK;
#if USBH_DEBUG_ENABLE_WARNINGS
if (!gintsts) {
uwarnf("GINTSTS=%08x, GINTMSK=%08x", otg->GINTSTS, otg->GINTMSK);
uint32_t a, b;
a = otg->GINTSTS;
b = otg->GINTMSK;
uwarnf("GINTSTS=%08x, GINTMSK=%08x", a, b);
return;
}
// otg->GINTMSK &= ~(GINTMSK_NPTXFEM | GINTMSK_PTXFEM);
#endif
// otg->GINTMSK &= ~(GINTMSK_NPTXFEM | GINTMSK_PTXFEM);
otg->GINTSTS = gintsts;
if (gintsts & GINTSTS_SOF)
@ -1437,6 +1507,7 @@ static void _usbh_start(USBHDriver *usbh) {
}
#endif
#endif
#undef HNPTXFSIZ
otg_txfifo_flush(usbh, 0x10);
otg_rxfifo_flush(usbh);
@ -1478,18 +1549,18 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
break;
case ClearPortFeature:
chDbgAssert(windex == 1, "invalid windex");
osalDbgAssert(windex == 1, "invalid windex");
osalSysLock();
switch (wvalue) {
case USBH_PORT_FEAT_ENABLE:
case USBH_PORT_FEAT_SUSPEND:
case USBH_PORT_FEAT_POWER:
chDbgAssert(0, "unimplemented"); /* TODO */
osalDbgAssert(0, "unimplemented"); /* TODO */
break;
case USBH_PORT_FEAT_INDICATOR:
chDbgAssert(0, "unsupported");
osalDbgAssert(0, "unsupported");
break;
case USBH_PORT_FEAT_C_CONNECTION:
@ -1541,7 +1612,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
break;
case GetPortStatus:
chDbgAssert(windex == 1, "invalid windex");
osalDbgAssert(windex == 1, "invalid windex");
osalDbgCheck(wlength >= 4);
osalSysLock();
*(uint32_t *)buf = usbh->rootport.lld_status | (usbh->rootport.lld_c_status << 16);
@ -1550,17 +1621,17 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
break;
case SetHubFeature:
chDbgAssert(0, "unsupported");
osalDbgAssert(0, "unsupported");
break;
case SetPortFeature:
chDbgAssert(windex == 1, "invalid windex");
osalDbgAssert(windex == 1, "invalid windex");
switch (wvalue) {
case USBH_PORT_FEAT_TEST:
case USBH_PORT_FEAT_SUSPEND:
case USBH_PORT_FEAT_POWER:
chDbgAssert(0, "unimplemented"); /* TODO */
osalDbgAssert(0, "unimplemented"); /* TODO */
break;
case USBH_PORT_FEAT_RESET: {
@ -1580,7 +1651,7 @@ usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestTy
} break;
case USBH_PORT_FEAT_INDICATOR:
chDbgAssert(0, "unsupported");
osalDbgAssert(0, "unsupported");
break;
default:

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -127,25 +127,26 @@ typedef struct stm32_hc_management {
"use USBH_DEFINE_BUFFER() to declare the IO buffers"); \
} while (0)
void usbh_lld_init(void);
void usbh_lld_start(USBHDriver *usbh);
void usbh_lld_ep_object_init(usbh_ep_t *ep);
void usbh_lld_ep_open(usbh_ep_t *ep);
void usbh_lld_ep_close(usbh_ep_t *ep);
bool usbh_lld_ep_reset(usbh_ep_t *ep);
void usbh_lld_urb_submit(usbh_urb_t *urb);
bool usbh_lld_urb_abort(usbh_urb_t *urb, usbh_urbstatus_t status);
usbh_urbstatus_t usbh_lld_root_hub_request(USBHDriver *usbh, uint8_t bmRequestType, uint8_t bRequest,
uint16_t wvalue, uint16_t windex, uint16_t wlength, uint8_t *buf);
uint8_t usbh_lld_roothub_get_statuschange_bitmap(USBHDriver *usbh);
#define usbh_lld_epreset(ep) do {(ep)->dt_mask = HCTSIZ_DPID_DATA0;} while (0);
#ifdef __IAR_SYSTEMS_ICC__
#define USBH_LLD_DEFINE_BUFFER(type, name) type name
#define USBH_LLD_DEFINE_BUFFER(var) _Pragma("data_alignment=4") var
#define USBH_LLD_DECLARE_STRUCT_MEMBER_H1(x, y) x ## y
#define USBH_LLD_DECLARE_STRUCT_MEMBER_H2(x, y) USBH_LLD_DECLARE_STRUCT_MEMBER_H1(x, y)
#define USBH_LLD_DECLARE_STRUCT_MEMBER(member) unsigned int USBH_LLD_DECLARE_STRUCT_MEMBER_H2(dummy_align_, __COUNTER__); member
#else
#define USBH_LLD_DEFINE_BUFFER(type, name) type name __attribute__((aligned(4)))
#define USBH_LLD_DEFINE_BUFFER(var) var __attribute__((aligned(4)))
#define USBH_LLD_DECLARE_STRUCT_MEMBER(member) member __attribute__((aligned(4)))
#endif
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,10 +19,17 @@
#if HAL_USE_USBH
#include "usbh/dev/hub.h"
#include "usbh/internal.h"
#include <string.h>
//devices
#include "usbh/dev/hub.h"
#include "usbh/dev/aoa.h"
#include "usbh/dev/ftdi.h"
#include "usbh/dev/msd.h"
#include "usbh/dev/hid.h"
#include "usbh/dev/uvc.h"
#if USBH_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
@ -107,11 +114,23 @@ void usbhObjectInit(USBHDriver *usbh) {
}
void usbhInit(void) {
#if HAL_USBH_USE_FTDI
usbhftdiInit();
#endif
#if HAL_USBH_USE_AOA
usbhaoaInit();
#endif
#if HAL_USBH_USE_MSD
usbhmsdInit();
#endif
#if HAL_USBH_USE_HID
usbhhidInit();
#endif
#if HAL_USBH_USE_UVC
usbhuvcInit();
#endif
#if HAL_USBH_USE_HUB
uint8_t i;
for (i = 0; i < HAL_USBHHUB_MAX_INSTANCES; i++) {
usbhhubObjectInit(&USBHHUBD[i]);
}
usbhhubInit();
#endif
usbh_lld_init();
}
@ -128,7 +147,6 @@ void usbhStart(USBHDriver *usbh) {
osalSysUnlock();
}
void usbhStop(USBHDriver *usbh) {
//TODO: implement
(void)usbh;
@ -181,6 +199,25 @@ static void _ep0_object_init(usbh_device_t *dev, uint16_t wMaxPacketSize) {
usbhEPSetName(&dev->ctrl, "DEV[CTRL]");
}
bool usbhEPReset(usbh_ep_t *ep) {
osalDbgCheck(ep != NULL);
osalDbgAssert((ep->status == USBH_EPSTATUS_OPEN) || (ep->status == USBH_EPSTATUS_HALTED), "invalid state");
osalDbgAssert(ep->type != USBH_EPTYPE_CTRL, "don't need to reset control endpoint");
usbh_urbstatus_t ret = usbhControlRequest(ep->device,
USBH_REQTYPE_STANDARDOUT(USBH_REQTYPE_RECIP_ENDPOINT),
USBH_REQ_CLEAR_FEATURE,
0, ep->address | (ep->in ? 0x80 : 0x00), 0, 0);
/* TODO: GET_STATUS to see if endpoint is still halted */
osalSysLock();
if ((ret == USBH_URBSTATUS_OK) && usbh_lld_ep_reset(ep)) {
osalSysUnlock();
return HAL_SUCCESS;
}
osalSysUnlock();
return HAL_FAILED;
}
/*===========================================================================*/
/* URB API. */
@ -258,7 +295,6 @@ bool _usbh_urb_abortI(usbh_urb_t *urb, usbh_urbstatus_t status) {
_usbh_urb_completeI(urb, status);
return TRUE;
// case USBH_URBSTATUS_QUEUED:
case USBH_URBSTATUS_PENDING:
return usbh_lld_urb_abort(urb, status);
}
@ -271,11 +307,18 @@ void _usbh_urb_abort_and_waitS(usbh_urb_t *urb, usbh_urbstatus_t status) {
if (_usbh_urb_abortI(urb, status) == FALSE) {
uwarn("URB wasn't aborted immediately, suspend");
osalThreadSuspendS(&urb->abortingThread);
urb->abortingThread = 0;
} else {
osalDbgAssert(urb->abortingThread == 0, "maybe we should uncomment the line below");
//urb->abortingThread = 0;
}
#if !(USBH_DEBUG_ENABLE && USBH_DEBUG_ENABLE_WARNINGS)
else {
osalOsRescheduleS();
}
#else
uwarn("URB aborted");
osalOsRescheduleS(); /* debug printing functions call I-class functions inside
which may cause a priority violation without this call */
#endif
}
bool usbhURBCancelI(usbh_urb_t *urb) {
@ -295,9 +338,9 @@ msg_t usbhURBWaitTimeoutS(usbh_urb_t *urb, systime_t timeout) {
switch (urb->status) {
case USBH_URBSTATUS_INITIALIZED:
case USBH_URBSTATUS_PENDING:
// case USBH_URBSTATUS_QUEUED:
ret = osalThreadSuspendTimeoutS(&urb->waitingThread, timeout);
urb->waitingThread = 0;
osalDbgAssert(urb->waitingThread == 0, "maybe we should uncomment the line below");
//urb->waitingThread = 0;
break;
case USBH_URBSTATUS_OK:
@ -382,7 +425,8 @@ usbh_urbstatus_t usbhControlRequestExtended(usbh_device_t *dev,
uint32_t *actual_len,
systime_t timeout) {
_check_dev(dev);
if (!dev) return USBH_URBSTATUS_DISCONNECTED;
osalDbgCheck(req != NULL);
usbh_urb_t urb;
@ -408,7 +452,7 @@ usbh_urbstatus_t usbhControlRequest(usbh_device_t *dev,
uint16_t wLength,
uint8_t *buff) {
const USBH_DEFINE_BUFFER(usbh_control_request_t, req) = {
USBH_DEFINE_BUFFER(const usbh_control_request_t req) = {
bmRequestType,
bRequest,
wValue,
@ -422,27 +466,19 @@ usbh_urbstatus_t usbhControlRequest(usbh_device_t *dev,
/* Standard request helpers. */
/*===========================================================================*/
#define USBH_GET_DESCRIPTOR(type, value, index) \
USBH_STANDARDIN(type, \
USBH_REQ_GET_DESCRIPTOR, \
value, \
index) \
#define USBH_GETDEVICEDESCRIPTOR \
USBH_GET_DESCRIPTOR(USBH_REQTYPE_DEVICE, (USBH_DT_DEVICE << 8) | 0, 0)
#define USBH_GETCONFIGURATIONDESCRIPTOR(index) \
USBH_GET_DESCRIPTOR(USBH_REQTYPE_DEVICE, (USBH_DT_CONFIG << 8) | index, 0)
#define USBH_GETSTRINGDESCRIPTOR(index, langID) \
USBH_GET_DESCRIPTOR(USBH_REQTYPE_DEVICE, (USBH_DT_STRING << 8) | index, langID)
bool usbhStdReqGetDeviceDescriptor(usbh_device_t *dev,
uint16_t wLength,
uint8_t *buf) {
usbh_device_descriptor_t *desc;
usbh_urbstatus_t ret = usbhControlRequest(dev, USBH_GETDEVICEDESCRIPTOR, wLength, buf);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_STANDARDIN(USBH_REQTYPE_RECIP_DEVICE),
USBH_REQ_GET_DESCRIPTOR,
(USBH_DT_DEVICE << 8) | 0, 0,
wLength, buf);
desc = (usbh_device_descriptor_t *)buf;
if ((ret != USBH_URBSTATUS_OK)
|| (desc->bLength != USBH_DT_DEVICE_SIZE)
|| (desc->bDescriptorType != USBH_DT_DEVICE)) {
@ -455,8 +491,15 @@ bool usbhStdReqGetConfigurationDescriptor(usbh_device_t *dev,
uint8_t index,
uint16_t wLength,
uint8_t *buf) {
usbh_urbstatus_t ret = usbhControlRequest(dev, USBH_GETCONFIGURATIONDESCRIPTOR(index), wLength, buf);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_STANDARDIN(USBH_REQTYPE_RECIP_DEVICE),
USBH_REQ_GET_DESCRIPTOR,
(USBH_DT_CONFIG << 8) | index, 0,
wLength, buf);
usbh_config_descriptor_t *const desc = (usbh_config_descriptor_t *)buf;
if ((ret != USBH_URBSTATUS_OK)
|| (desc->bLength < USBH_DT_CONFIG_SIZE)
|| (desc->bDescriptorType != USBH_DT_CONFIG)) {
@ -473,7 +516,13 @@ bool usbhStdReqGetStringDescriptor(usbh_device_t *dev,
osalDbgAssert(wLength >= USBH_DT_STRING_SIZE, "wrong size");
usbh_string_descriptor_t *desc = (usbh_string_descriptor_t *)buf;
usbh_urbstatus_t ret = usbhControlRequest(dev, USBH_GETSTRINGDESCRIPTOR(index, langID), wLength, buf);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_STANDARDIN(USBH_REQTYPE_RECIP_DEVICE),
USBH_REQ_GET_DESCRIPTOR,
(USBH_DT_STRING << 8) | index, langID,
wLength, buf);
if ((ret != USBH_URBSTATUS_OK)
|| (desc->bLength < USBH_DT_STRING_SIZE)
|| (desc->bDescriptorType != USBH_DT_STRING)) {
@ -482,25 +531,17 @@ bool usbhStdReqGetStringDescriptor(usbh_device_t *dev,
return HAL_SUCCESS;
}
#define USBH_SET_INTERFACE(interface, alt) \
USBH_STANDARDOUT(USBH_REQTYPE_INTERFACE, \
USBH_REQ_SET_INTERFACE, \
alt, \
interface) \
#define USBH_GET_INTERFACE(interface) \
USBH_STANDARDIN(USBH_REQTYPE_INTERFACE, \
USBH_REQ_GET_INTERFACE, \
0, \
interface) \
bool usbhStdReqSetInterface(usbh_device_t *dev,
uint8_t bInterfaceNumber,
uint8_t bAlternateSetting) {
usbh_urbstatus_t ret = usbhControlRequest(dev, USBH_SET_INTERFACE(bInterfaceNumber, bAlternateSetting), 0, NULL);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_STANDARDOUT(USBH_REQTYPE_RECIP_INTERFACE),
USBH_REQ_SET_INTERFACE,
bAlternateSetting,
bInterfaceNumber,
0, NULL);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
@ -511,9 +552,15 @@ bool usbhStdReqGetInterface(usbh_device_t *dev,
uint8_t bInterfaceNumber,
uint8_t *bAlternateSetting) {
USBH_DEFINE_BUFFER(uint8_t, alt);
USBH_DEFINE_BUFFER(uint8_t alt);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_STANDARDIN(USBH_REQTYPE_RECIP_INTERFACE),
USBH_REQ_GET_INTERFACE,
0,
bInterfaceNumber,
1, &alt);
usbh_urbstatus_t ret = usbhControlRequest(dev, USBH_GET_INTERFACE(bInterfaceNumber), 1, &alt);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
@ -558,7 +605,8 @@ static void _device_initialize(usbh_device_t *dev, usbh_devspeed_t speed) {
static bool _device_setaddress(usbh_device_t *dev, uint8_t address) {
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_STANDARDOUT(USBH_REQTYPE_DEVICE, USBH_REQ_SET_ADDRESS, address, 0),
USBH_REQTYPE_STANDARDOUT(USBH_REQTYPE_RECIP_DEVICE),
USBH_REQ_SET_ADDRESS, address, 0,
0,
0);
if (ret != USBH_URBSTATUS_OK)
@ -611,22 +659,12 @@ static void _device_free_full_cfgdesc(usbh_device_t *dev) {
}
}
#define USBH_SET_CONFIGURATION(type, value, index) \
USBH_STANDARDOUT(type, \
USBH_REQ_SET_CONFIGURATION, \
value, \
index) \
#define USBH_SETDEVICECONFIGURATION(index) \
USBH_SET_CONFIGURATION(USBH_REQTYPE_DEVICE, index, 0)
static bool _device_set_configuration(usbh_device_t *dev, uint8_t configuration) {
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_SETDEVICECONFIGURATION(configuration),
0,
0);
USBH_REQTYPE_STANDARDOUT(USBH_REQTYPE_RECIP_DEVICE),
USBH_REQ_SET_CONFIGURATION,
configuration,
0, 0, 0);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
return HAL_SUCCESS;
@ -720,7 +758,7 @@ static bool _device_enumerate(usbh_device_t *dev) {
#if USBH_DEBUG_ENABLE && USBH_DEBUG_ENABLE_INFO
void usbhDevicePrintInfo(usbh_device_t *dev) {
USBH_DEFINE_BUFFER(char, str[64]);
USBH_DEFINE_BUFFER(char str[64]);
usbh_device_descriptor_t *const desc = &dev->devDesc;
uinfo("----- Device info -----");
@ -856,7 +894,7 @@ static void _port_reset(usbh_port_t *port) {
#if HAL_USBH_USE_HUB
port->hub,
#endif
USBH_REQTYPE_OUT | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_SET_FEATURE,
USBH_PORT_FEAT_RESET,
port->number,
@ -870,7 +908,7 @@ static void _port_update_status(usbh_port_t *port) {
#if HAL_USBH_USE_HUB
port->hub,
#endif
USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_OTHER,
USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_OTHER,
USBH_REQ_GET_STATUS,
0,
port->number,
@ -934,7 +972,7 @@ static void _port_connected(usbh_port_t *port) {
uint8_t i;
uint8_t retries;
usbh_devspeed_t speed;
USBH_DEFINE_BUFFER(usbh_string_descriptor_t, strdesc);
USBH_DEFINE_BUFFER(usbh_string_descriptor_t strdesc);
uinfof("Port %d connected, wait debounce...", port->number);
@ -1086,7 +1124,7 @@ static void _hub_update_status(USBHDriver *host, USBHHubDriver *hub) {
uint32_t stat;
if (usbhhubControlRequest(host,
hub,
USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE,
USBH_REQ_GET_STATUS,
0,
0,
@ -1274,8 +1312,17 @@ static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = {
#if HAL_USBH_USE_MSD
&usbhmsdClassDriverInfo,
#endif
#if HAL_USBH_USE_HID
&usbhhidClassDriverInfo,
#endif
#if HAL_USBH_USE_UVC
&usbhuvcClassDriverInfo,
#endif
#if HAL_USBH_USE_HUB
&usbhhubClassDriverInfo
&usbhhubClassDriverInfo,
#endif
#if HAL_USBH_USE_AOA
&usbhaoaClassDriverInfo, /* Leave always last */
#endif
};
@ -1302,7 +1349,7 @@ static bool _classdriver_load(usbh_device_t *dev, uint8_t class,
#if HAL_USBH_USE_IAD
/* special case: */
if (info == &usbhiadClassDriverInfo)
return HAL_SUCCESS;
goto success; //return HAL_SUCCESS;
#endif
if (drv != NULL)
@ -1313,9 +1360,11 @@ static bool _classdriver_load(usbh_device_t *dev, uint8_t class,
success:
/* Link this driver to the device */
drv->next = dev->drivers;
dev->drivers = drv;
drv->dev = dev;
if (!drv->dev) {
drv->next = dev->drivers;
dev->drivers = drv;
drv->dev = dev;
}
return HAL_SUCCESS;
}

View File

@ -0,0 +1,678 @@
/*
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#if HAL_USBH_USE_AOA
#if !HAL_USE_USBH
#error "USBHAOA needs USBH"
#endif
#include <string.h>
#include "usbh/dev/aoa.h"
#include "usbh/internal.h"
//#pragma GCC optimize("Og")
#if USBHAOA_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHAOA_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHAOA_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHAOA_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
/*===========================================================================*/
/* Constants */
/*===========================================================================*/
#if !defined(HAL_USBHAOA_DEFAULT_MANUFACTURER)
#define HAL_USBHAOA_DEFAULT_MANUFACTURER "ChibiOS"
#endif
#if !defined(HAL_USBHAOA_DEFAULT_MODEL)
#define HAL_USBHAOA_DEFAULT_MODEL "USBH AOA Driver"
#endif
#if !defined(HAL_USBHAOA_DEFAULT_DESCRIPTION)
#define HAL_USBHAOA_DEFAULT_DESCRIPTION "ChibiOS USBH AOA Driver"
#endif
#if !defined(HAL_USBHAOA_DEFAULT_VERSION)
#define HAL_USBHAOA_DEFAULT_VERSION CH_KERNEL_VERSION
#endif
#if !defined(HAL_USBHAOA_DEFAULT_URI)
#define HAL_USBHAOA_DEFAULT_URI NULL
#endif
#if !defined(HAL_USBHAOA_DEFAULT_SERIAL)
#define HAL_USBHAOA_DEFAULT_SERIAL NULL
#endif
#if !defined(HAL_USBHAOA_DEFAULT_AUDIO_MODE)
#define HAL_USBHAOA_DEFAULT_AUDIO_MODE USBHAOA_AUDIO_MODE_DISABLED
#endif
#define AOA_GOOGLE_VID 0x18D1
#define AOA_GOOGLE_PID_ACCESSORY 0x2D00
#define AOA_GOOGLE_PID_ACCESSORY_ABD 0x2D01
#define AOA_GOOGLE_PID_AUDIO 0x2D02
#define AOA_GOOGLE_PID_AUDIO_ABD 0x2D03
#define AOA_GOOGLE_PID_ACCESSORY_AUDIO 0x2D04
#define AOA_GOOGLE_PID_ACCESSORY_AUDIO_ABD 0x2D05
#define AOA_ACCESSORY_GET_PROTOCOL 51
#define AOA_ACCESSORY_SEND_STRING 52
#define AOA_ACCESSORY_START 53
#define AOA_SET_AUDIO_MODE 58
static bool _get_protocol(usbh_device_t *dev, uint16_t *protocol);
static bool _accessory_start(usbh_device_t *dev);
static bool _set_audio_mode(usbh_device_t *dev, uint16_t mode);
static bool _send_string(usbh_device_t *dev, uint8_t index, const char *string);
static void _stop_channelS(USBHAOAChannel *aoacp);
/*===========================================================================*/
/* USB Class driver loader for AOA */
/*===========================================================================*/
USBHAOADriver USBHAOAD[HAL_USBHAOA_MAX_INSTANCES];
static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void _aoa_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t class_driver_vmt = {
_aoa_load,
_aoa_unload
};
const usbh_classdriverinfo_t usbhaoaClassDriverInfo = {
0xff, 0xff, 0xff, "AOA", &class_driver_vmt
};
#if defined(HAL_USBHAOA_FILTER_CALLBACK)
extern usbhaoa_filter_callback_t HAL_USBHAOA_FILTER_CALLBACK;
#endif
static usbh_baseclassdriver_t *_aoa_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
int i;
USBHAOADriver *aoap;
if (dev->devDesc.idVendor != AOA_GOOGLE_VID) {
uint16_t protocol;
static const USBHAOAConfig config = {
{
HAL_USBHAOA_DEFAULT_MANUFACTURER,
HAL_USBHAOA_DEFAULT_MODEL,
HAL_USBHAOA_DEFAULT_DESCRIPTION,
HAL_USBHAOA_DEFAULT_VERSION,
HAL_USBHAOA_DEFAULT_URI,
HAL_USBHAOA_DEFAULT_SERIAL
},
{
HAL_USBHAOA_DEFAULT_AUDIO_MODE,
}
};
uinfo("AOA: Unrecognized VID");
#if defined(HAL_USBHAOA_FILTER_CALLBACK)
if (!HAL_USBHAOA_FILTER_CALLBACK(dev, descriptor, rem, &config)) {
return NULL;
}
#endif
uinfo("AOA: Try if it's an Android device");
if (_get_protocol(dev, &protocol) != HAL_SUCCESS) {
return NULL;
}
uinfof("AOA: Possible Android device found (protocol=%d)", protocol);
if (config.channel.manufacturer != NULL) {
if ((_send_string(dev, USBHAOA_ACCESSORY_STRING_MANUFACTURER, config.channel.manufacturer) != HAL_SUCCESS)
|| (_send_string(dev, USBHAOA_ACCESSORY_STRING_MODEL, config.channel.model) != HAL_SUCCESS)
|| (_send_string(dev, USBHAOA_ACCESSORY_STRING_DESCRIPTION, config.channel.description) != HAL_SUCCESS)
|| (_send_string(dev, USBHAOA_ACCESSORY_STRING_VERSION, config.channel.version) != HAL_SUCCESS)
|| (_send_string(dev, USBHAOA_ACCESSORY_STRING_URI, config.channel.uri) != HAL_SUCCESS)
|| (_send_string(dev, USBHAOA_ACCESSORY_STRING_SERIAL, config.channel.serial) != HAL_SUCCESS)) {
uerr("AOA: Can't send string; abort start");
return NULL;
}
}
if (protocol > 1) {
if (_set_audio_mode(dev, (uint16_t)(config.audio.mode)) != HAL_SUCCESS) {
uerr("AOA: Can't set audio mode; abort channel start");
return NULL;
}
}
if (_accessory_start(dev) != HAL_SUCCESS) {
uerr("AOA: Can't start accessory; abort channel start");
}
return NULL;
}
/* AOAv2:
0x2D00 accessory Provides two bulk endpoints for communicating with an Android application.
0x2D01 accessory + adb For debugging purposes during accessory development. Available only if the user has enabled USB Debugging in the Android device settings.
0x2D02 audio For streaming audio from an Android device to an accessory.
0x2D03 audio + adb
0x2D04 accessory + audio
0x2D05 accessory + audio + adb
*/
switch (dev->devDesc.idProduct) {
case AOA_GOOGLE_PID_ACCESSORY:
case AOA_GOOGLE_PID_ACCESSORY_ABD:
// case AOA_GOOGLE_PID_AUDIO:
// case AOA_GOOGLE_PID_AUDIO_ABD:
case AOA_GOOGLE_PID_ACCESSORY_AUDIO:
case AOA_GOOGLE_PID_ACCESSORY_AUDIO_ABD:
break;
default:
uerr("AOA: Unrecognized PID");
return NULL;
}
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor;
if ((ifdesc->bInterfaceClass != 0xff)
|| (ifdesc->bInterfaceSubClass != 0xff)
|| (ifdesc->bInterfaceProtocol != 0x00)
|| (ifdesc->bNumEndpoints < 2)) {
uerr("AOA: This IF is not the Accessory IF");
return NULL;
}
uinfof("AOA: Found Accessory Interface #%d", ifdesc->bInterfaceNumber);
for (i = 0; i < HAL_USBHAOA_MAX_INSTANCES; i++) {
if (USBHAOAD[i].dev == NULL) {
aoap = &USBHAOAD[i];
goto alloc_ok;
}
}
uwarn("AOA: Can't alloc driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
usbhEPSetName(&dev->ctrl, "AOA[CTRL]");
aoap->state = USBHAOA_STATE_ACTIVE;
generic_iterator_t iep;
if_iterator_t iif;
iif.iad = 0;
iif.curr = descriptor;
iif.rem = rem;
aoap->channel.epin.status = USBH_EPSTATUS_UNINITIALIZED;
aoap->channel.epout.status = USBH_EPSTATUS_UNINITIALIZED;
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("AOA: BULK IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&aoap->channel.epin, dev, epdesc);
usbhEPSetName(&aoap->channel.epin, "AOA[BIN ]");
} else if (((epdesc->bEndpointAddress & 0x80) == 0)
&& (epdesc->bmAttributes == USBH_EPTYPE_BULK)) {
uinfof("AOA: BULK OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&aoap->channel.epout, dev, epdesc);
usbhEPSetName(&aoap->channel.epout, "AOA[BOUT]");
} else {
uinfof("AOA: unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bmAttributes);
}
}
if ((aoap->channel.epin.status != USBH_EPSTATUS_CLOSED)
|| (aoap->channel.epout.status != USBH_EPSTATUS_CLOSED)) {
uwarn("AOA: Couldn't find endpoints");
aoap->state = USBHAOA_STATE_STOP;
return NULL;
}
aoap->state = USBHAOA_STATE_READY;
aoap->channel.state = USBHAOA_CHANNEL_STATE_ACTIVE;
uwarn("AOA: Ready");
return (usbh_baseclassdriver_t *)aoap;
}
static void _aoa_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHAOADriver *const aoap = (USBHAOADriver *)drv;
osalSysLock();
_stop_channelS(&aoap->channel);
aoap->channel.state = USBHAOA_CHANNEL_STATE_STOP;
aoap->state = USBHAOA_STATE_STOP;
osalOsRescheduleS();
osalSysUnlock();
}
/* ------------------------------------ */
/* Accessory data channel */
/* ------------------------------------ */
static void _submitOutI(USBHAOAChannel *aoacp, uint32_t len) {
udbgf("AOA: Submit OUT %d", len);
aoacp->oq_urb.requestedLength = len;
usbhURBObjectResetI(&aoacp->oq_urb);
usbhURBSubmitI(&aoacp->oq_urb);
}
static void _out_cb(usbh_urb_t *urb) {
USBHAOAChannel *const aoacp = (USBHAOAChannel *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
aoacp->oq_ptr = aoacp->oq_buff;
aoacp->oq_counter = 64;
chThdDequeueNextI(&aoacp->oq_waiting, Q_OK);
chnAddFlagsI(aoacp, CHN_OUTPUT_EMPTY | CHN_TRANSMISSION_END);
return;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("AOA: URB OUT disconnected");
chThdDequeueNextI(&aoacp->oq_waiting, Q_RESET);
chnAddFlagsI(aoacp, CHN_OUTPUT_EMPTY);
return;
default:
uerrf("AOA: URB OUT status unexpected = %d", urb->status);
break;
}
usbhURBObjectResetI(&aoacp->oq_urb);
usbhURBSubmitI(&aoacp->oq_urb);
}
static size_t _write_timeout(USBHAOAChannel *aoacp, const uint8_t *bp,
size_t n, systime_t timeout) {
chDbgCheck(n > 0U);
size_t w = 0;
chSysLock();
while (true) {
if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) {
chSysUnlock();
return w;
}
while (usbhURBIsBusy(&aoacp->oq_urb)) {
if (chThdEnqueueTimeoutS(&aoacp->oq_waiting, timeout) != Q_OK) {
chSysUnlock();
return w;
}
}
*aoacp->oq_ptr++ = *bp++;
if (--aoacp->oq_counter == 0) {
_submitOutI(aoacp, 64);
chSchRescheduleS();
}
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
w++;
if (--n == 0U)
return w;
chSysLock();
}
}
static msg_t _put_timeout(USBHAOAChannel *aoacp, uint8_t b, systime_t timeout) {
chSysLock();
if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) {
chSysUnlock();
return Q_RESET;
}
while (usbhURBIsBusy(&aoacp->oq_urb)) {
msg_t msg = chThdEnqueueTimeoutS(&aoacp->oq_waiting, timeout);
if (msg < Q_OK) {
chSysUnlock();
return msg;
}
}
*aoacp->oq_ptr++ = b;
if (--aoacp->oq_counter == 0) {
_submitOutI(aoacp, 64);
chSchRescheduleS();
}
chSysUnlock();
return Q_OK;
}
static size_t _write(USBHAOAChannel *aoacp, const uint8_t *bp, size_t n) {
return _write_timeout(aoacp, bp, n, TIME_INFINITE);
}
static msg_t _put(USBHAOAChannel *aoacp, uint8_t b) {
return _put_timeout(aoacp, b, TIME_INFINITE);
}
static void _submitInI(USBHAOAChannel *aoacp) {
udbg("AOA: Submit IN");
usbhURBObjectResetI(&aoacp->iq_urb);
usbhURBSubmitI(&aoacp->iq_urb);
}
static void _in_cb(usbh_urb_t *urb) {
USBHAOAChannel *const aoacp = (USBHAOAChannel *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
if (urb->actualLength == 0) {
udbgf("AOA: URB IN no data");
} else {
udbgf("AOA: URB IN data len=%d", urb->actualLength);
aoacp->iq_ptr = aoacp->iq_buff;
aoacp->iq_counter = urb->actualLength;
chThdDequeueNextI(&aoacp->iq_waiting, Q_OK);
chnAddFlagsI(aoacp, CHN_INPUT_AVAILABLE);
}
break;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("AOA: URB IN disconnected");
chThdDequeueNextI(&aoacp->iq_waiting, Q_RESET);
break;
default:
uerrf("AOA: URB IN status unexpected = %d", urb->status);
_submitInI(aoacp);
break;
}
}
static size_t _read_timeout(USBHAOAChannel *aoacp, uint8_t *bp,
size_t n, systime_t timeout) {
size_t r = 0;
chDbgCheck(n > 0U);
chSysLock();
while (true) {
if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) {
chSysUnlock();
return r;
}
while (aoacp->iq_counter == 0) {
if (!usbhURBIsBusy(&aoacp->iq_urb))
_submitInI(aoacp);
if (chThdEnqueueTimeoutS(&aoacp->iq_waiting, timeout) != Q_OK) {
chSysUnlock();
return r;
}
}
*bp++ = *aoacp->iq_ptr++;
if (--aoacp->iq_counter == 0) {
_submitInI(aoacp);
chSchRescheduleS();
}
chSysUnlock();
r++;
if (--n == 0U)
return r;
chSysLock();
}
}
static msg_t _get_timeout(USBHAOAChannel *aoacp, systime_t timeout) {
uint8_t b;
chSysLock();
if (aoacp->state != USBHAOA_CHANNEL_STATE_READY) {
chSysUnlock();
return Q_RESET;
}
while (aoacp->iq_counter == 0) {
if (!usbhURBIsBusy(&aoacp->iq_urb))
_submitInI(aoacp);
msg_t msg = chThdEnqueueTimeoutS(&aoacp->iq_waiting, timeout);
if (msg < Q_OK) {
chSysUnlock();
return msg;
}
}
b = *aoacp->iq_ptr++;
if (--aoacp->iq_counter == 0) {
_submitInI(aoacp);
chSchRescheduleS();
}
chSysUnlock();
return (msg_t)b;
}
static msg_t _get(USBHAOAChannel *aoacp) {
return _get_timeout(aoacp, TIME_INFINITE);
}
static size_t _read(USBHAOAChannel *aoacp, uint8_t *bp, size_t n) {
return _read_timeout(aoacp, bp, n, TIME_INFINITE);
}
static const struct AOADriverVMT async_channel_vmt = {
(size_t (*)(void *, const uint8_t *, size_t))_write,
(size_t (*)(void *, uint8_t *, size_t))_read,
(msg_t (*)(void *, uint8_t))_put,
(msg_t (*)(void *))_get,
(msg_t (*)(void *, uint8_t, systime_t))_put_timeout,
(msg_t (*)(void *, systime_t))_get_timeout,
(size_t (*)(void *, const uint8_t *, size_t, systime_t))_write_timeout,
(size_t (*)(void *, uint8_t *, size_t, systime_t))_read_timeout
};
static void _stop_channelS(USBHAOAChannel *aoacp) {
if (aoacp->state != USBHAOA_CHANNEL_STATE_READY)
return;
uwarn("AOA: Stop channel");
chVTResetI(&aoacp->vt);
usbhEPCloseS(&aoacp->epin);
usbhEPCloseS(&aoacp->epout);
chThdDequeueAllI(&aoacp->iq_waiting, Q_RESET);
chThdDequeueAllI(&aoacp->oq_waiting, Q_RESET);
chnAddFlagsI(aoacp, CHN_DISCONNECTED);
aoacp->state = USBHAOA_CHANNEL_STATE_ACTIVE;
}
static void _vt(void *p) {
USBHAOAChannel *const aoacp = (USBHAOAChannel *)p;
chSysLockFromISR();
uint32_t len = aoacp->oq_ptr - aoacp->oq_buff;
if (len && !usbhURBIsBusy(&aoacp->oq_urb)) {
_submitOutI(aoacp, len);
}
if ((aoacp->iq_counter == 0) && !usbhURBIsBusy(&aoacp->iq_urb)) {
_submitInI(aoacp);
}
chVTSetI(&aoacp->vt, MS2ST(16), _vt, aoacp);
chSysUnlockFromISR();
}
void usbhaoaChannelStart(USBHAOADriver *aoap) {
osalDbgCheck(aoap);
USBHAOAChannel *const aoacp = (USBHAOAChannel *)&aoap->channel;
osalDbgCheck(aoap->state == USBHAOA_STATE_READY);
osalDbgCheck((aoacp->state == USBHAOA_CHANNEL_STATE_ACTIVE)
|| (aoacp->state == USBHAOA_CHANNEL_STATE_READY));
if (aoacp->state == USBHAOA_CHANNEL_STATE_READY)
return;
usbhURBObjectInit(&aoacp->oq_urb, &aoacp->epout, _out_cb, aoacp, aoacp->oq_buff, 0);
chThdQueueObjectInit(&aoacp->oq_waiting);
aoacp->oq_counter = 64;
aoacp->oq_ptr = aoacp->oq_buff;
usbhEPOpen(&aoacp->epout);
usbhURBObjectInit(&aoacp->iq_urb, &aoacp->epin, _in_cb, aoacp, aoacp->iq_buff, 64);
chThdQueueObjectInit(&aoacp->iq_waiting);
aoacp->iq_counter = 0;
aoacp->iq_ptr = aoacp->iq_buff;
usbhEPOpen(&aoacp->epin);
osalSysLock();
usbhURBSubmitI(&aoacp->iq_urb);
osalSysUnlock();
chVTObjectInit(&aoacp->vt);
chVTSet(&aoacp->vt, MS2ST(16), _vt, aoacp);
aoacp->state = USBHAOA_CHANNEL_STATE_READY;
osalEventBroadcastFlags(&aoacp->event, CHN_CONNECTED | CHN_OUTPUT_EMPTY);
}
void usbhaoaChannelStop(USBHAOADriver *aoap) {
osalDbgCheck((aoap->channel.state == USBHAOA_CHANNEL_STATE_ACTIVE)
|| (aoap->channel.state == USBHAOA_CHANNEL_STATE_READY));
osalSysLock();
_stop_channelS(&aoap->channel);
osalOsRescheduleS();
osalSysUnlock();
}
/* ------------------------------------ */
/* General AOA functions */
/* ------------------------------------ */
static bool _get_protocol(usbh_device_t *dev, uint16_t *protocol) {
USBH_DEFINE_BUFFER(uint16_t proto);
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_RECIP_DEVICE,
AOA_ACCESSORY_GET_PROTOCOL,
0,
0,
2,
(uint8_t *)&proto);
if ((ret != USBH_URBSTATUS_OK) || (proto > 2))
return HAL_FAILED;
*protocol = proto;
return HAL_SUCCESS;
}
static bool _accessory_start(usbh_device_t *dev) {
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_RECIP_DEVICE,
AOA_ACCESSORY_START,
0,
0,
0,
NULL);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
return HAL_SUCCESS;
}
static bool _set_audio_mode(usbh_device_t *dev, uint16_t mode) {
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_RECIP_DEVICE,
AOA_SET_AUDIO_MODE,
mode,
0,
0,
NULL);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
return HAL_SUCCESS;
}
static bool _send_string(usbh_device_t *dev, uint8_t index, const char *string)
{
USBH_DEFINE_BUFFER(const char nullstr[1]) = {0};
if (string == NULL)
string = nullstr;
usbh_urbstatus_t ret = usbhControlRequest(dev,
USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_RECIP_DEVICE,
AOA_ACCESSORY_SEND_STRING,
0,
index,
strlen(string) + 1,
(uint8_t *)string);
if (ret != USBH_URBSTATUS_OK)
return HAL_FAILED;
return HAL_SUCCESS;
}
void usbhaoaObjectInit(USBHAOADriver *aoap) {
osalDbgCheck(aoap != NULL);
memset(aoap, 0, sizeof(*aoap));
aoap->info = &usbhaoaClassDriverInfo;
aoap->state = USBHAOA_STATE_STOP;
aoap->channel.vmt = &async_channel_vmt;
osalEventObjectInit(&aoap->channel.event);
aoap->channel.state = USBHAOA_CHANNEL_STATE_STOP;
}
void usbhaoaInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHAOA_MAX_INSTANCES; i++) {
usbhaoaObjectInit(&USBHAOAD[i]);
}
}
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,15 +17,13 @@
#include "hal.h"
#if HAL_USE_USBH
#if HAL_USE_USBH && USBH_DEBUG_ENABLE
#include "ch.h"
#include "usbh/debug.h"
#include <stdarg.h>
#include "chprintf.h"
#if USBH_DEBUG_ENABLE
#define MAX_FILLER 11
#define FLOAT_PRECISION 9
#define MPRINTF_USE_FLOAT 0
@ -472,8 +470,8 @@ void usbDbgSystemHalted(void) {
}
}
static void usb_debug_thread(void *p) {
USBHDriver *host = (USBHDriver *)p;
static void usb_debug_thread(void *arg) {
USBHDriver *host = (USBHDriver *)arg;
uint8_t state = 0;
chRegSetThreadName("USBH_DBG");
@ -531,6 +529,5 @@ void usbDbgInit(USBHDriver *host) {
iqObjectInit(&USBH_DEBUG_USBHD.iq, USBH_DEBUG_USBHD.dbg_buff, sizeof(USBH_DEBUG_USBHD.dbg_buff), 0, 0);
chThdCreateStatic(USBH_DEBUG_USBHD.waDebug, sizeof(USBH_DEBUG_USBHD.waDebug), NORMALPRIO, usb_debug_thread, &USBH_DEBUG_USBHD);
}
#endif
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -134,22 +134,18 @@ void cs_iter_next(generic_iterator_t *ics) {
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
//for (;;) {
rem -= curr[0];
curr += curr[0];
rem -= curr[0];
curr += curr[0];
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
if ((curr[0] < 2) || (rem < 2) || (rem < curr[0]))
return;
if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION)
|| (curr[1] == USBH_DT_INTERFACE)
|| (curr[1] == USBH_DT_CONFIG)
|| (curr[1] == USBH_DT_ENDPOINT)) {
return;
}
// break;
//}
if ((curr[1] == USBH_DT_INTERFACE_ASSOCIATION)
|| (curr[1] == USBH_DT_INTERFACE)
|| (curr[1] == USBH_DT_CONFIG)
|| (curr[1] == USBH_DT_ENDPOINT)) {
return;
}
ics->valid = 1;
ics->rem = rem;

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
*/
#include "hal.h"
#include "hal_usbh.h"
#if HAL_USBH_USE_FTDI
@ -105,6 +104,7 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des
case 0x6011:
case 0x6014:
case 0x6015:
case 0xE2E6:
break;
default:
uerr("FTDI: Unrecognized PID");
@ -114,8 +114,7 @@ static usbh_baseclassdriver_t *_ftdi_load(usbh_device_t *dev, const uint8_t *des
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t * const)descriptor;
if (ifdesc->bInterfaceNumber != 0) {
if (((const usbh_interface_descriptor_t *)descriptor)->bInterfaceNumber != 0) {
uwarn("FTDI: Will allocate driver along with IF #0");
}
@ -211,7 +210,7 @@ alloc_ok:
}
static void _stop(USBHFTDIPortDriver *ftdipp);
static void _stopS(USBHFTDIPortDriver *ftdipp);
static void _ftdi_unload(usbh_baseclassdriver_t *drv) {
osalDbgCheck(drv != NULL);
USBHFTDIDriver *const ftdip = (USBHFTDIDriver *)drv;
@ -219,7 +218,10 @@ static void _ftdi_unload(usbh_baseclassdriver_t *drv) {
osalMutexLock(&ftdip->mtx);
while (ftdipp) {
_stop(ftdipp);
osalSysLock();
_stopS(ftdipp);
osalOsRescheduleS();
osalSysUnlock();
ftdipp = ftdipp->next;
}
@ -314,17 +316,17 @@ static usbh_urbstatus_t _ftdi_port_control(USBHFTDIPortDriver *ftdipp,
uint8_t *buff) {
static const uint8_t bmRequestType[] = {
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //0 FTDI_COMMAND_RESET
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //1 FTDI_COMMAND_MODEMCTRL
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //2 FTDI_COMMAND_SETFLOW
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //3 FTDI_COMMAND_SETBAUD
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE, //4 FTDI_COMMAND_SETDATA
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE, //0 FTDI_COMMAND_RESET
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE, //1 FTDI_COMMAND_MODEMCTRL
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE, //2 FTDI_COMMAND_SETFLOW
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE, //3 FTDI_COMMAND_SETBAUD
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE, //4 FTDI_COMMAND_SETDATA
};
osalDbgCheck(bRequest < sizeof_array(bmRequestType));
osalDbgCheck(bRequest != 1);
const USBH_DEFINE_BUFFER(usbh_control_request_t, req) = {
USBH_DEFINE_BUFFER(const usbh_control_request_t req) = {
bmRequestType[bRequest],
bRequest,
wValue,
@ -387,8 +389,8 @@ static usbh_urbstatus_t _set_baudrate(USBHFTDIPortDriver *ftdipp, uint32_t baudr
if (ftdipp->ftdip->dev->basicConfigDesc.bNumInterfaces > 1)
wIndex = (wIndex << 8) | (ftdipp->ifnum + 1);
const USBH_DEFINE_BUFFER(usbh_control_request_t, req) = {
USBH_REQTYPE_VENDOR | USBH_REQTYPE_OUT | USBH_REQTYPE_DEVICE,
USBH_DEFINE_BUFFER(const usbh_control_request_t req) = {
USBH_REQTYPE_TYPE_VENDOR | USBH_REQTYPE_DIR_OUT | USBH_REQTYPE_RECIP_DEVICE,
FTDI_COMMAND_SETBAUD,
wValue,
wIndex,
@ -626,29 +628,27 @@ static const struct FTDIPortDriverVMT async_channel_vmt = {
};
static void _stop(USBHFTDIPortDriver *ftdipp) {
osalSysLock();
static void _stopS(USBHFTDIPortDriver *ftdipp) {
if (ftdipp->state != USBHFTDIP_STATE_READY)
return;
chVTResetI(&ftdipp->vt);
usbhEPCloseS(&ftdipp->epin);
usbhEPCloseS(&ftdipp->epout);
chThdDequeueAllI(&ftdipp->iq_waiting, Q_RESET);
chThdDequeueAllI(&ftdipp->oq_waiting, Q_RESET);
osalOsRescheduleS();
ftdipp->state = USBHFTDIP_STATE_ACTIVE;
osalSysUnlock();
}
void usbhftdipStop(USBHFTDIPortDriver *ftdipp) {
osalDbgCheck((ftdipp->state == USBHFTDIP_STATE_ACTIVE)
|| (ftdipp->state == USBHFTDIP_STATE_READY));
if (ftdipp->state == USBHFTDIP_STATE_ACTIVE) {
return;
}
osalMutexLock(&ftdipp->ftdip->mtx);
_stop(ftdipp);
osalMutexUnlock(&ftdipp->ftdip->mtx);
osalSysLock();
chMtxLockS(&ftdipp->ftdip->mtx);
_stopS(ftdipp);
chMtxUnlockS(&ftdipp->ftdip->mtx);
osalOsRescheduleS();
osalSysUnlock();
}
void usbhftdipStart(USBHFTDIPortDriver *ftdipp, const USBHFTDIPortConfig *config) {
@ -714,4 +714,14 @@ void usbhftdipObjectInit(USBHFTDIPortDriver *ftdipp) {
ftdipp->state = USBHFTDIP_STATE_STOP;
}
void usbhftdiInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHFTDI_MAX_INSTANCES; i++) {
usbhftdiObjectInit(&USBHFTDID[i]);
}
for (i = 0; i < HAL_USBHFTDI_MAX_PORTS; i++) {
usbhftdipObjectInit(&FTDIPD[i]);
}
}
#endif

View File

@ -0,0 +1,322 @@
/*
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#if HAL_USBH_USE_HID
#if !HAL_USE_USBH
#error "USBHHID needs USBH"
#endif
#include <string.h>
#include "usbh/dev/hid.h"
#include "usbh/internal.h"
#if USBHHID_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define udbgf(f, ...) do {} while(0)
#define udbg(f, ...) do {} while(0)
#endif
#if USBHHID_DEBUG_ENABLE_INFO
#define uinfof(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uinfo(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uinfof(f, ...) do {} while(0)
#define uinfo(f, ...) do {} while(0)
#endif
#if USBHHID_DEBUG_ENABLE_WARNINGS
#define uwarnf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uwarn(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uwarnf(f, ...) do {} while(0)
#define uwarn(f, ...) do {} while(0)
#endif
#if USBHHID_DEBUG_ENABLE_ERRORS
#define uerrf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define uerr(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
#else
#define uerrf(f, ...) do {} while(0)
#define uerr(f, ...) do {} while(0)
#endif
#define USBH_HID_REQ_GET_REPORT 0x01
#define USBH_HID_REQ_GET_IDLE 0x02
#define USBH_HID_REQ_GET_PROTOCOL 0x03
#define USBH_HID_REQ_SET_REPORT 0x09
#define USBH_HID_REQ_SET_IDLE 0x0A
#define USBH_HID_REQ_SET_PROTOCOL 0x0B
/*===========================================================================*/
/* USB Class driver loader for MSD */
/*===========================================================================*/
USBHHIDDriver USBHHIDD[HAL_USBHHID_MAX_INSTANCES];
static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void _hid_unload(usbh_baseclassdriver_t *drv);
static const usbh_classdriver_vmt_t class_driver_vmt = {
_hid_load,
_hid_unload
};
const usbh_classdriverinfo_t usbhhidClassDriverInfo = {
0x03, -1, -1, "HID", &class_driver_vmt
};
static usbh_baseclassdriver_t *_hid_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
int i;
USBHHIDDriver *hidp;
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
const usbh_interface_descriptor_t * const ifdesc = (const usbh_interface_descriptor_t *)descriptor;
if ((ifdesc->bAlternateSetting != 0)
|| (ifdesc->bNumEndpoints < 1)) {
return NULL;
}
/* alloc driver */
for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) {
if (USBHHIDD[i].dev == NULL) {
hidp = &USBHHIDD[i];
goto alloc_ok;
}
}
uwarn("Can't alloc HID driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
hidp->epin.status = USBH_EPSTATUS_UNINITIALIZED;
#if HAL_USBHHID_USE_INTERRUPT_OUT
hidp->epout.status = USBH_EPSTATUS_UNINITIALIZED;
#endif
hidp->ifnum = ifdesc->bInterfaceNumber;
usbhEPSetName(&dev->ctrl, "HID[CTRL]");
/* parse the configuration descriptor */
if_iterator_t iif;
generic_iterator_t iep;
iif.iad = 0;
iif.curr = descriptor;
iif.rem = rem;
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((epdesc->bEndpointAddress & 0x80) && (epdesc->bmAttributes == USBH_EPTYPE_INT)) {
uinfof("INT IN endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&hidp->epin, dev, epdesc);
usbhEPSetName(&hidp->epin, "HID[IIN ]");
#if HAL_USBHHID_USE_INTERRUPT_OUT
} else if (((epdesc->bEndpointAddress & 0x80) == 0)
&& (epdesc->bmAttributes == USBH_EPTYPE_INT)) {
uinfof("INT OUT endpoint found: bEndpointAddress=%02x", epdesc->bEndpointAddress);
usbhEPObjectInit(&hidp->epout, dev, epdesc);
usbhEPSetName(&hidp->epout, "HID[IOUT]");
#endif
} else {
uinfof("unsupported endpoint found: bEndpointAddress=%02x, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bmAttributes);
}
}
if (hidp->epin.status != USBH_EPSTATUS_CLOSED) {
goto deinit;
}
if (ifdesc->bInterfaceSubClass != 0x01) {
hidp->type = USBHHID_DEVTYPE_GENERIC;
uinfof("HID: bInterfaceSubClass=%02x, generic HID", ifdesc->bInterfaceSubClass);
if (ifdesc->bInterfaceSubClass != 0x00) {
uinfof("HID: bInterfaceSubClass=%02x is an invalid bInterfaceSubClass value",
ifdesc->bInterfaceSubClass);
}
} else if (ifdesc->bInterfaceProtocol == 0x01) {
hidp->type = USBHHID_DEVTYPE_BOOT_KEYBOARD;
uinfo("HID: BOOT protocol keyboard found");
} else if (ifdesc->bInterfaceProtocol == 0x02) {
hidp->type = USBHHID_DEVTYPE_BOOT_MOUSE;
uinfo("HID: BOOT protocol mouse found");
} else {
uerrf("HID: bInterfaceProtocol=%02x is an invalid boot protocol, abort",
ifdesc->bInterfaceProtocol);
goto deinit;
}
hidp->state = USBHHID_STATE_ACTIVE;
return (usbh_baseclassdriver_t *)hidp;
deinit:
/* Here, the enpoints are closed, and the driver is unlinked */
return NULL;
}
static void _hid_unload(usbh_baseclassdriver_t *drv) {
(void)drv;
}
static void _in_cb(usbh_urb_t *urb) {
USBHHIDDriver *const hidp = (USBHHIDDriver *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
if (hidp->config->cb_report) {
hidp->config->cb_report(hidp, urb->actualLength);
}
break;
case USBH_URBSTATUS_DISCONNECTED:
uwarn("HID: URB IN disconnected");
return;
case USBH_URBSTATUS_TIMEOUT:
//no data
break;
default:
uerrf("HID: URB IN status unexpected = %d", urb->status);
break;
}
usbhURBObjectResetI(&hidp->in_urb);
usbhURBSubmitI(&hidp->in_urb);
}
void usbhhidStart(USBHHIDDriver *hidp, const USBHHIDConfig *cfg) {
osalDbgCheck(hidp && cfg);
osalDbgCheck(cfg->report_buffer && (cfg->protocol <= USBHHID_PROTOCOL_REPORT));
osalDbgCheck((hidp->state == USBHHID_STATE_ACTIVE)
|| (hidp->state == USBHHID_STATE_READY));
if (hidp->state == USBHHID_STATE_READY)
return;
hidp->config = cfg;
/* init the URBs */
usbhURBObjectInit(&hidp->in_urb, &hidp->epin, _in_cb, hidp,
cfg->report_buffer, cfg->report_len);
/* open the int IN/OUT endpoints */
usbhEPOpen(&hidp->epin);
#if HAL_USBHHID_USE_INTERRUPT_OUT
if (hidp->epout.status == USBH_EPSTATUS_CLOSED) {
usbhEPOpen(&hidp->epout);
}
#endif
usbhhidSetProtocol(hidp, cfg->protocol);
osalSysLock();
usbhURBSubmitI(&hidp->in_urb);
osalSysUnlock();
hidp->state = USBHHID_STATE_READY;
}
void usbhhidStop(USBHHIDDriver *hidp) {
osalDbgCheck((hidp->state == USBHHID_STATE_ACTIVE)
|| (hidp->state == USBHHID_STATE_READY));
if (hidp->state != USBHHID_STATE_READY)
return;
osalSysLock();
usbhEPCloseS(&hidp->epin);
#if HAL_USBHHID_USE_INTERRUPT_OUT
if (hidp->epout.status != USBH_EPSTATUS_UNINITIALIZED) {
usbhEPCloseS(&hidp->epout);
}
#endif
hidp->state = USBHHID_STATE_ACTIVE;
osalSysUnlock();
}
usbh_urbstatus_t usbhhidGetReport(USBHHIDDriver *hidp,
uint8_t report_id, usbhhid_reporttype_t report_type,
void *data, uint16_t len) {
osalDbgCheck(hidp);
osalDbgAssert((uint8_t)report_type <= USBHHID_REPORTTYPE_FEATURE, "wrong report type");
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_REPORT,
((uint8_t)report_type << 8) | report_id, hidp->ifnum, len, data);
}
usbh_urbstatus_t usbhhidSetReport(USBHHIDDriver *hidp,
uint8_t report_id, usbhhid_reporttype_t report_type,
const void *data, uint16_t len) {
osalDbgCheck(hidp);
osalDbgAssert((uint8_t)report_type <= USBHHID_REPORTTYPE_FEATURE, "wrong report type");
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_REPORT,
((uint8_t)report_type << 8) | report_id, hidp->ifnum, len, (void *)data);
}
usbh_urbstatus_t usbhhidGetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t *duration) {
osalDbgCheck(hidp);
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_IDLE,
report_id, hidp->ifnum, 1, duration);
}
usbh_urbstatus_t usbhhidSetIdle(USBHHIDDriver *hidp, uint8_t report_id, uint8_t duration) {
osalDbgCheck(hidp);
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_IDLE,
(duration << 8) | report_id, hidp->ifnum, 0, NULL);
}
usbh_urbstatus_t usbhhidGetProtocol(USBHHIDDriver *hidp, uint8_t *protocol) {
osalDbgCheck(hidp);
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_GET_PROTOCOL,
0, hidp->ifnum, 1, protocol);
}
usbh_urbstatus_t usbhhidSetProtocol(USBHHIDDriver *hidp, uint8_t protocol) {
osalDbgCheck(hidp);
osalDbgAssert(protocol <= 1, "invalid protocol");
return usbhControlRequest(hidp->dev,
USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE), USBH_HID_REQ_SET_PROTOCOL,
protocol, hidp->ifnum, 0, NULL);
}
void usbhhidObjectInit(USBHHIDDriver *hidp) {
osalDbgCheck(hidp != NULL);
memset(hidp, 0, sizeof(*hidp));
hidp->info = &usbhhidClassDriverInfo;
hidp->state = USBHHID_STATE_STOP;
}
void usbhhidInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHHID_MAX_INSTANCES; i++) {
usbhhidObjectInit(&USBHHIDD[i]);
}
}
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -15,10 +15,7 @@
limitations under the License.
*/
#include <string.h>
#include "hal.h"
#include "hal_usbh.h"
#include "usbh/internal.h"
#if HAL_USBH_USE_HUB
@ -28,6 +25,7 @@
#include <string.h>
#include "usbh/dev/hub.h"
#include "usbh/internal.h"
#if USBHHUB_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
@ -63,7 +61,7 @@
USBHHubDriver USBHHUBD[HAL_USBHHUB_MAX_INSTANCES];
usbh_port_t USBHPorts[HAL_USBHHUB_MAX_PORTS];
static usbh_port_t USBHPorts[HAL_USBHHUB_MAX_PORTS];
static usbh_baseclassdriver_t *hub_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem);
static void hub_unload(usbh_baseclassdriver_t *drv);
@ -200,7 +198,7 @@ alloc_ok:
/* read Hub descriptor */
uinfo("Read Hub descriptor");
if (usbhhubControlRequest(dev->host, hubdp,
USBH_REQTYPE_IN | USBH_REQTYPE_CLASS | USBH_REQTYPE_DEVICE,
USBH_REQTYPE_DIR_IN | USBH_REQTYPE_TYPE_CLASS | USBH_REQTYPE_RECIP_DEVICE,
USBH_REQ_GET_DESCRIPTOR,
(USBH_DT_HUB << 8), 0, sizeof(hubdp->hubDesc),
(uint8_t *)&hubdp->hubDesc) != USBH_URBSTATUS_OK) {
@ -290,9 +288,18 @@ void usbhhubObjectInit(USBHHubDriver *hubdp) {
memset(hubdp, 0, sizeof(*hubdp));
hubdp->info = &usbhhubClassDriverInfo;
}
void usbhhubInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHHUB_MAX_INSTANCES; i++) {
usbhhubObjectInit(&USBHHUBD[i]);
}
}
#else
#if HAL_USE_USBH
#include <string.h>
void _usbhub_port_object_init(usbh_port_t *port, USBHDriver *usbh, uint8_t number) {
memset(port, 0, sizeof(*port));
port->number = number;

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
*/
#include "hal.h"
#include "hal_usbh.h"
#if HAL_USBH_USE_MSD
@ -91,8 +90,8 @@ const usbh_classdriverinfo_t usbhmsdClassDriverInfo = {
static usbh_baseclassdriver_t *_msd_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
int i;
USBHMassStorageDriver *msdp;
uint8_t luns; // should declare it here to eliminate 'control bypass initialization' warning
usbh_urbstatus_t stat; // should declare it here to eliminate 'control bypass initialization' warning
uint8_t luns;
usbh_urbstatus_t stat;
if ((rem < descriptor[0]) || (descriptor[1] != USBH_DT_INTERFACE))
return NULL;
@ -157,10 +156,10 @@ alloc_ok:
/* read the number of LUNs */
uinfo("Reading Max LUN:");
USBH_DEFINE_BUFFER(uint8_t, buff[4]);
USBH_DEFINE_BUFFER(uint8_t buff[4]);
stat = usbhControlRequest(dev,
USBH_CLASSIN(USBH_REQTYPE_INTERFACE, MSD_GET_MAX_LUN, 0, msdp->ifnum),
1, buff);
USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE),
MSD_GET_MAX_LUN, 0, msdp->ifnum, 1, buff);
if (stat == USBH_URBSTATUS_OK) {
msdp->max_lun = buff[0] + 1;
uinfof("\tmax_lun = %d", msdp->max_lun);
@ -194,7 +193,9 @@ alloc_ok:
osalSysUnlock();
/* connect the LUN (TODO: review if it's best to leave the LUN disconnected) */
msdp->dev = dev;
usbhmsdLUNConnect(&MSBLKD[i]);
msdp->dev = NULL;
luns--;
}
}
@ -240,7 +241,7 @@ static void _msd_unload(usbh_baseclassdriver_t *drv) {
/* USB Bulk Only Transport SCSI Command block wrapper */
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint32_t dCBWSignature;
uint32_t dCBWTag;
uint32_t dCBWDataTransferLength;
@ -253,9 +254,8 @@ PACKED_STRUCT {
#define MSD_CBWFLAGS_D2H 0x80
#define MSD_CBWFLAGS_H2D 0x00
/* USB Bulk Only Transport SCSI Command status wrapper */
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
@ -263,32 +263,172 @@ PACKED_STRUCT {
} msd_csw_t;
#define MSD_CSW_SIGNATURE 0x53425355
typedef union {
msd_cbw_t cbw;
msd_csw_t csw;
typedef struct {
msd_cbw_t *cbw;
uint8_t csw_status;
uint32_t data_processed;
} msd_transaction_t;
typedef enum {
MSD_TRANSACTIONRESULT_OK,
MSD_TRANSACTIONRESULT_DISCONNECTED,
MSD_TRANSACTIONRESULT_STALL,
MSD_TRANSACTIONRESULT_BUS_ERROR,
MSD_TRANSACTIONRESULT_SYNC_ERROR
} msd_transaction_result_t;
MSD_BOTRESULT_OK,
MSD_BOTRESULT_DISCONNECTED,
MSD_BOTRESULT_ERROR
} msd_bot_result_t;
typedef enum {
MSD_COMMANDRESULT_PASSED = 0,
MSD_COMMANDRESULT_FAILED = 1,
MSD_COMMANDRESULT_PHASE_ERROR = 2
} msd_command_result_t;
typedef struct {
msd_transaction_result_t tres;
msd_command_result_t cres;
MSD_RESULT_OK = MSD_BOTRESULT_OK,
MSD_RESULT_DISCONNECTED = MSD_BOTRESULT_DISCONNECTED,
MSD_RESULT_TRANSPORT_ERROR = MSD_BOTRESULT_ERROR,
MSD_RESULT_FAILED
} msd_result_t;
#define CSW_STATUS_PASSED 0
#define CSW_STATUS_FAILED 1
#define CSW_STATUS_PHASE_ERROR 2
static bool _msd_bot_reset(USBHMassStorageDriver *msdp) {
usbh_urbstatus_t res;
res = usbhControlRequest(msdp->dev,
USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE),
0xFF, 0, msdp->ifnum, 0, NULL);
if (res != USBH_URBSTATUS_OK) {
return FALSE;
}
osalThreadSleepMilliseconds(100);
return usbhEPReset(&msdp->epin) && usbhEPReset(&msdp->epout);
}
static msd_bot_result_t _msd_bot_transaction(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp, void *data) {
uint32_t data_actual_len, actual_len;
usbh_urbstatus_t status;
USBH_DEFINE_BUFFER(msd_csw_t csw);
tran->cbw->bCBWLUN = (uint8_t)(lunp - &lunp->msdp->luns[0]);
tran->cbw->dCBWSignature = MSD_CBW_SIGNATURE;
tran->cbw->dCBWTag = ++lunp->msdp->tag;
tran->data_processed = 0;
/* control phase */
status = usbhBulkTransfer(&lunp->msdp->epout, tran->cbw,
sizeof(*tran->cbw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED");
return MSD_BOTRESULT_DISCONNECTED;
}
if ((status != USBH_URBSTATUS_OK) || (actual_len != sizeof(*tran->cbw))) {
uerrf("\tMSD: Control phase: status = %d (!= OK), actual_len = %d (expected to send %d)",
status, actual_len, sizeof(*tran->cbw));
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
/* data phase */
data_actual_len = 0;
if (tran->cbw->dCBWDataTransferLength) {
usbh_ep_t *const ep = tran->cbw->bmCBWFlags & MSD_CBWFLAGS_D2H ? &lunp->msdp->epin : &lunp->msdp->epout;
status = usbhBulkTransfer(
ep,
data,
tran->cbw->dCBWDataTransferLength,
&data_actual_len, MS2ST(20000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED");
return MSD_BOTRESULT_DISCONNECTED;
}
if (status == USBH_URBSTATUS_STALL) {
uerrf("\tMSD: Data phase: USBH_URBSTATUS_STALL, clear halt");
status = usbhEPReset(ep);
}
if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Data phase: status = %d (!= OK), resetting", status);
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
}
/* status phase */
status = usbhBulkTransfer(&lunp->msdp->epin, &csw,
sizeof(csw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_STALL) {
uwarn("\tMSD: Status phase: USBH_URBSTATUS_STALL, clear halt and retry");
status = usbhEPReset(&lunp->msdp->epin);
if (status == USBH_URBSTATUS_OK) {
status = usbhBulkTransfer(&lunp->msdp->epin, &csw,
sizeof(csw), &actual_len, MS2ST(1000));
}
}
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED");
return MSD_BOTRESULT_DISCONNECTED;
}
if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Status phase: status = %d (!= OK), resetting", status);
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
/* validate CSW */
if ((actual_len != sizeof(csw))
|| (csw.dCSWSignature != MSD_CSW_SIGNATURE)
|| (csw.dCSWTag != lunp->msdp->tag)
|| (csw.bCSWStatus >= CSW_STATUS_PHASE_ERROR)) {
/* CSW is not valid */
uerrf("\tMSD: Status phase: Invalid CSW: len=%d, dCSWSignature=%x, dCSWTag=%x (expected %x), bCSWStatus=%d, resetting",
actual_len,
csw.dCSWSignature,
csw.dCSWTag,
lunp->msdp->tag,
csw.bCSWStatus);
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
/* check if CSW is meaningful */
if ((csw.bCSWStatus != CSW_STATUS_PHASE_ERROR)
&& (csw.dCSWDataResidue > tran->cbw->dCBWDataTransferLength)) {
/* CSW is not meaningful */
uerrf("\tMSD: Status phase: CSW not meaningful: bCSWStatus=%d, dCSWDataResidue=%u, dCBWDataTransferLength=%u, resetting",
csw.bCSWStatus,
csw.dCSWDataResidue,
tran->cbw->dCBWDataTransferLength);
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
if (csw.bCSWStatus == CSW_STATUS_PHASE_ERROR) {
uerr("\tMSD: Status phase: Phase error, resetting");
_msd_bot_reset(lunp->msdp);
return MSD_BOTRESULT_ERROR;
}
tran->data_processed = tran->cbw->dCBWDataTransferLength - csw.dCSWDataResidue;
if (data_actual_len < tran->data_processed) {
tran->data_processed = data_actual_len;
}
tran->csw_status = csw.bCSWStatus;
return MSD_BOTRESULT_OK;
}
/* ----------------------------------------------------- */
/* SCSI Commands */
/* ----------------------------------------------------- */
@ -299,7 +439,7 @@ typedef struct {
/* Request sense */
#define SCSI_CMD_REQUEST_SENSE 0x03
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t byte[18];
} scsi_sense_response_t;
@ -333,7 +473,7 @@ PACKED_STRUCT {
/* Inquiry */
#define SCSI_CMD_INQUIRY 0x12
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t peripheral;
uint8_t removable;
uint8_t version;
@ -349,14 +489,14 @@ PACKED_STRUCT {
/* Read Capacity 10 */
#define SCSI_CMD_READ_CAPACITY_10 0x25
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint32_t last_block_addr;
uint32_t block_size;
} scsi_readcapacity10_response_t;
/* Start/Stop Unit */
#define SCSI_CMD_START_STOP_UNIT 0x1B
PACKED_STRUCT {
typedef PACKED_STRUCT {
uint8_t op_code;
uint8_t lun_immed;
uint8_t res1;
@ -368,216 +508,180 @@ PACKED_STRUCT {
/* test unit ready */
#define SCSI_CMD_TEST_UNIT_READY 0x00
/* Other commands, TODO: use or remove them
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define SCSI_CMD_MODE_SENSE_6 0x1A
*/
static msd_result_t scsi_requestsense(USBHMassStorageLUNDriver *lunp, scsi_sense_response_t *resp);
static inline void _prepare_cbw(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp) {
tran->cbw.bCBWLUN = (uint8_t)(lunp - &lunp->msdp->luns[0]);
memset(&tran->cbw.CBWCB, 0, sizeof(tran->cbw.CBWCB));
}
static msd_result_t _scsi_perform_transaction(USBHMassStorageLUNDriver *lunp,
msd_transaction_t *transaction, void *data) {
static msd_transaction_result_t _msd_transaction(msd_transaction_t *tran, USBHMassStorageLUNDriver *lunp, void *data) {
uint32_t actual_len;
usbh_urbstatus_t status;
tran->cbw.dCBWSignature = MSD_CBW_SIGNATURE;
tran->cbw.dCBWTag = ++lunp->msdp->tag;
/* control phase */
status = usbhBulkTransfer(&lunp->msdp->epout, &tran->cbw,
sizeof(tran->cbw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Control phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Control phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Control phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != sizeof(tran->cbw)) {
uerrf("\tMSD: Control phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
msd_bot_result_t res;
res = _msd_bot_transaction(transaction, lunp, data);
if (res != MSD_BOTRESULT_OK) {
return (msd_result_t)res;
}
/* data phase */
if (tran->cbw.dCBWDataTransferLength) {
status = usbhBulkTransfer(
tran->cbw.bmCBWFlags & MSD_CBWFLAGS_D2H ? &lunp->msdp->epin : &lunp->msdp->epout,
data,
tran->cbw.dCBWDataTransferLength,
&actual_len, MS2ST(20000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Data phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Data phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Data phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != tran->cbw.dCBWDataTransferLength) {
uerrf("\tMSD: Data phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
if (transaction->csw_status == CSW_STATUS_FAILED) {
if (transaction->cbw->CBWCB[0] != SCSI_CMD_REQUEST_SENSE) {
/* do auto-sense (except for SCSI_CMD_REQUEST_SENSE!) */
uwarn("\tMSD: Command failed, auto-sense");
USBH_DEFINE_BUFFER(scsi_sense_response_t sense);
if (scsi_requestsense(lunp, &sense) == MSD_RESULT_OK) {
uwarnf("\tMSD: REQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x",
sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]);
}
}
return MSD_RESULT_FAILED;
}
/* status phase */
status = usbhBulkTransfer(&lunp->msdp->epin, &tran->csw,
sizeof(tran->csw), &actual_len, MS2ST(1000));
if (status == USBH_URBSTATUS_CANCELLED) {
uerr("\tMSD: Status phase: USBH_URBSTATUS_CANCELLED");
return MSD_TRANSACTIONRESULT_DISCONNECTED;
} else if (status == USBH_URBSTATUS_STALL) {
uerr("\tMSD: Status phase: USBH_URBSTATUS_STALL");
return MSD_TRANSACTIONRESULT_STALL;
} else if (status != USBH_URBSTATUS_OK) {
uerrf("\tMSD: Status phase: status = %d, != OK", status);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (actual_len != sizeof(tran->csw)) {
uerrf("\tMSD: Status phase: wrong actual_len = %d", actual_len);
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (tran->csw.dCSWSignature != MSD_CSW_SIGNATURE) {
uerr("\tMSD: Status phase: wrong signature");
return MSD_TRANSACTIONRESULT_BUS_ERROR;
} else if (tran->csw.dCSWTag != lunp->msdp->tag) {
uerrf("\tMSD: Status phase: wrong tag (expected %d, got %d)",
lunp->msdp->tag, tran->csw.dCSWTag);
return MSD_TRANSACTIONRESULT_SYNC_ERROR;
}
if (tran->csw.dCSWDataResidue) {
uwarnf("\tMSD: Residue=%d", tran->csw.dCSWDataResidue);
}
return MSD_TRANSACTIONRESULT_OK;
return MSD_RESULT_OK;
}
static msd_result_t scsi_inquiry(USBHMassStorageLUNDriver *lunp, scsi_inquiry_response_t *resp) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_inquiry_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 6;
transaction.cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
transaction.cbw.CBWCB[4] = sizeof(scsi_inquiry_response_t);
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = sizeof(scsi_inquiry_response_t);
cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
cbw.bCBWCBLength = 6;
cbw.CBWCB[0] = SCSI_CMD_INQUIRY;
cbw.CBWCB[4] = sizeof(scsi_inquiry_response_t);
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
res = _scsi_perform_transaction(lunp, &transaction, resp);
if (res == MSD_RESULT_OK) {
//transaction is OK; check length
if (transaction.data_processed < cbw.dCBWDataTransferLength) {
res = MSD_RESULT_TRANSPORT_ERROR;
}
}
return res;
}
static msd_result_t scsi_requestsense(USBHMassStorageLUNDriver *lunp, scsi_sense_response_t *resp) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_sense_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 12;
transaction.cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
transaction.cbw.CBWCB[4] = sizeof(scsi_sense_response_t);
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = sizeof(scsi_sense_response_t);
cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
cbw.bCBWCBLength = 12;
cbw.CBWCB[0] = SCSI_CMD_REQUEST_SENSE;
cbw.CBWCB[4] = sizeof(scsi_sense_response_t);
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
res = _scsi_perform_transaction(lunp, &transaction, resp);
if (res == MSD_RESULT_OK) {
//transaction is OK; check length
if (transaction.data_processed < cbw.dCBWDataTransferLength) {
res = MSD_RESULT_TRANSPORT_ERROR;
}
}
return res;
}
static msd_result_t scsi_testunitready(USBHMassStorageLUNDriver *lunp) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = 0;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 6;
transaction.cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY;
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = 0;
cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
cbw.bCBWCBLength = 6;
cbw.CBWCB[0] = SCSI_CMD_TEST_UNIT_READY;
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, NULL);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
}
return res;
return _scsi_perform_transaction(lunp, &transaction, NULL);
}
static msd_result_t scsi_readcapacity10(USBHMassStorageLUNDriver *lunp, scsi_readcapacity10_response_t *resp) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = sizeof(scsi_readcapacity10_response_t);
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 12;
transaction.cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10;
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = sizeof(scsi_readcapacity10_response_t);
cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
cbw.bCBWCBLength = 12;
cbw.CBWCB[0] = SCSI_CMD_READ_CAPACITY_10;
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, resp);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
res = _scsi_perform_transaction(lunp, &transaction, resp);
if (res == MSD_RESULT_OK) {
//transaction is OK; check length
if (transaction.data_processed < cbw.dCBWDataTransferLength) {
res = MSD_RESULT_TRANSPORT_ERROR;
}
}
return res;
}
static msd_result_t scsi_read10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, uint8_t *data) {
static msd_result_t scsi_read10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, uint8_t *data, uint32_t *actual_len) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
transaction.cbw.bCBWCBLength = 10;
transaction.cbw.CBWCB[0] = SCSI_CMD_READ_10;
transaction.cbw.CBWCB[2] = (uint8_t)(lba >> 24);
transaction.cbw.CBWCB[3] = (uint8_t)(lba >> 16);
transaction.cbw.CBWCB[4] = (uint8_t)(lba >> 8);
transaction.cbw.CBWCB[5] = (uint8_t)(lba);
transaction.cbw.CBWCB[7] = (uint8_t)(n >> 8);
transaction.cbw.CBWCB[8] = (uint8_t)(n);
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
cbw.bmCBWFlags = MSD_CBWFLAGS_D2H;
cbw.bCBWCBLength = 10;
cbw.CBWCB[0] = SCSI_CMD_READ_10;
cbw.CBWCB[2] = (uint8_t)(lba >> 24);
cbw.CBWCB[3] = (uint8_t)(lba >> 16);
cbw.CBWCB[4] = (uint8_t)(lba >> 8);
cbw.CBWCB[5] = (uint8_t)(lba);
cbw.CBWCB[7] = (uint8_t)(n >> 8);
cbw.CBWCB[8] = (uint8_t)(n);
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, data);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
res = _scsi_perform_transaction(lunp, &transaction, data);
if (actual_len) {
*actual_len = transaction.data_processed;
}
if (res == MSD_RESULT_OK) {
//transaction is OK; check length
if (transaction.data_processed < cbw.dCBWDataTransferLength) {
res = MSD_RESULT_TRANSPORT_ERROR;
}
}
return res;
}
static msd_result_t scsi_write10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, const uint8_t *data) {
static msd_result_t scsi_write10(USBHMassStorageLUNDriver *lunp, uint32_t lba, uint16_t n, const uint8_t *data, uint32_t *actual_len) {
USBH_DEFINE_BUFFER(msd_cbw_t cbw);
msd_transaction_t transaction;
msd_result_t res;
_prepare_cbw(&transaction, lunp);
transaction.cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
transaction.cbw.bmCBWFlags = MSD_CBWFLAGS_H2D;
transaction.cbw.bCBWCBLength = 10;
transaction.cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
transaction.cbw.CBWCB[2] = (uint8_t)(lba >> 24);
transaction.cbw.CBWCB[3] = (uint8_t)(lba >> 16);
transaction.cbw.CBWCB[4] = (uint8_t)(lba >> 8);
transaction.cbw.CBWCB[5] = (uint8_t)(lba);
transaction.cbw.CBWCB[7] = (uint8_t)(n >> 8);
transaction.cbw.CBWCB[8] = (uint8_t)(n);
memset(cbw.CBWCB, 0, sizeof(cbw.CBWCB));
cbw.dCBWDataTransferLength = n * lunp->info.blk_size;
cbw.bmCBWFlags = MSD_CBWFLAGS_H2D;
cbw.bCBWCBLength = 10;
cbw.CBWCB[0] = SCSI_CMD_WRITE_10;
cbw.CBWCB[2] = (uint8_t)(lba >> 24);
cbw.CBWCB[3] = (uint8_t)(lba >> 16);
cbw.CBWCB[4] = (uint8_t)(lba >> 8);
cbw.CBWCB[5] = (uint8_t)(lba);
cbw.CBWCB[7] = (uint8_t)(n >> 8);
cbw.CBWCB[8] = (uint8_t)(n);
transaction.cbw = &cbw;
res.tres = _msd_transaction(&transaction, lunp, (uint8_t *)data);
if (res.tres == MSD_TRANSACTIONRESULT_OK) {
res.cres = (msd_command_result_t) transaction.csw.bCSWStatus;
res = _scsi_perform_transaction(lunp, &transaction, (void *)data);
if (actual_len) {
*actual_len = transaction.data_processed;
}
if (res == MSD_RESULT_OK) {
//transaction is OK; check length
if (transaction.data_processed < cbw.dCBWDataTransferLength) {
res = MSD_RESULT_TRANSPORT_ERROR;
}
}
return res;
}
@ -600,34 +704,6 @@ static const struct USBHMassStorageDriverVMT blk_vmt = {
(bool (*)(void *, BlockDeviceInfo *))usbhmsdLUNGetInfo
};
static uint32_t _requestsense(USBHMassStorageLUNDriver *lunp) {
scsi_sense_response_t sense;
msd_result_t res;
res = scsi_requestsense(lunp, &sense);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREQUEST SENSE: Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tREQUEST SENSE: Command Failed");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREQUEST SENSE: Command Phase Error");
goto failed;
}
uerrf("\tREQUEST SENSE: Sense key=%x, ASC=%02x, ASCQ=%02x",
sense.byte[2] & 0xf, sense.byte[12], sense.byte[13]);
return (sense.byte[2] & 0xf) | (sense.byte[12] << 8) | (sense.byte[13] << 16);
failed:
return 0xffffffff;
}
void usbhmsdLUNObjectInit(USBHMassStorageLUNDriver *lunp) {
osalDbgCheck(lunp != NULL);
memset(lunp, 0, sizeof(*lunp));
@ -680,71 +756,66 @@ bool usbhmsdLUNConnect(USBHMassStorageLUNDriver *lunp) {
osalMutexLock(&msdp->mtx);
USBH_DEFINE_BUFFER(union {
scsi_inquiry_response_t inq;
scsi_readcapacity10_response_t cap; }, u);
{
USBH_DEFINE_BUFFER(scsi_inquiry_response_t inq);
uinfo("INQUIRY...");
res = scsi_inquiry(lunp, &inq);
if (res == MSD_RESULT_DISCONNECTED) {
goto failed;
} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
//retry?
goto failed;
} else if (res == MSD_RESULT_FAILED) {
//retry?
goto failed;
}
uinfo("INQUIRY...");
res = scsi_inquiry(lunp, &u.inq);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tINQUIRY: Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tINQUIRY: Command Failed");
_requestsense(lunp);
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tINQUIRY: Command Phase Error");
goto failed;
}
uinfof("\tPDT=%02x", u.inq.peripheral & 0x1f);
if (u.inq.peripheral != 0) {
uerr("\tUnsupported PDT");
goto failed;
uinfof("\tPDT=%02x", inq.peripheral & 0x1f);
if (inq.peripheral != 0) {
uerr("\tUnsupported PDT");
goto failed;
}
}
// Test if unit ready
uint8_t i;
uint8_t i;
for (i = 0; i < 10; i++) {
uinfo("TEST UNIT READY...");
res = scsi_testunitready(lunp);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tTEST UNIT READY: Transaction error");
if (res == MSD_RESULT_DISCONNECTED) {
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tTEST UNIT READY: Command Failed");
_requestsense(lunp);
} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
//retry?
goto failed;
} else if (res == MSD_RESULT_FAILED) {
uinfo("\tTEST UNIT READY: Command Failed, retry");
osalThreadSleepMilliseconds(200);
continue;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tTEST UNIT READY: Command Phase Error");
goto failed;
}
uinfo("\tReady.");
break;
// osalThreadSleepMilliseconds(200); // will raise 'code is unreachable' warning
}
if (i == 10) goto failed;
// Read capacity
uinfo("READ CAPACITY(10)...");
res = scsi_readcapacity10(lunp, &u.cap);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREAD CAPACITY(10): Transaction error");
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
uerr("\tREAD CAPACITY(10): Command Failed");
_requestsense(lunp);
goto failed;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREAD CAPACITY(10): Command Phase Error");
goto failed;
{
USBH_DEFINE_BUFFER(scsi_readcapacity10_response_t cap);
// Read capacity
uinfo("READ CAPACITY(10)...");
res = scsi_readcapacity10(lunp, &cap);
if (res == MSD_RESULT_DISCONNECTED) {
goto failed;
} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
//retry?
goto failed;
} else if (res == MSD_RESULT_FAILED) {
//retry?
goto failed;
}
lunp->info.blk_size = __REV(cap.block_size);
lunp->info.blk_num = __REV(cap.last_block_addr) + 1;
}
lunp->info.blk_size = __REV(u.cap.block_size);
lunp->info.blk_num = __REV(u.cap.last_block_addr) + 1;
uinfof("\tBlock size=%dbytes, blocks=%u (~%u MB)", lunp->info.blk_size, lunp->info.blk_num,
(uint32_t)(((uint64_t)lunp->info.blk_size * lunp->info.blk_num) / (1024UL * 1024UL)));
@ -794,6 +865,7 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
bool ret = HAL_FAILED;
uint16_t blocks;
msd_result_t res;
uint32_t actual_len;
osalSysLock();
if (lunp->state != BLK_READY) {
@ -810,18 +882,14 @@ bool usbhmsdLUNRead(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
} else {
blocks = (uint16_t)n;
}
res = scsi_read10(lunp, startblk, blocks, buffer);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tREAD (10): Transaction error");
res = scsi_read10(lunp, startblk, blocks, buffer, &actual_len);
if (res == MSD_RESULT_DISCONNECTED) {
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
//TODO: request sense, and act appropriately
uerr("\tREAD (10): Command Failed");
_requestsense(lunp);
} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
//retry?
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tREAD (10): Command Phase Error");
} else if (res == MSD_RESULT_FAILED) {
//retry?
goto exit;
}
n -= blocks;
@ -851,6 +919,7 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
bool ret = HAL_FAILED;
uint16_t blocks;
msd_result_t res;
uint32_t actual_len;
osalSysLock();
if (lunp->state != BLK_READY) {
@ -867,18 +936,14 @@ bool usbhmsdLUNWrite(USBHMassStorageLUNDriver *lunp, uint32_t startblk,
} else {
blocks = (uint16_t)n;
}
res = scsi_write10(lunp, startblk, blocks, buffer);
if (res.tres != MSD_TRANSACTIONRESULT_OK) {
uerr("\tWRITE (10): Transaction error");
res = scsi_write10(lunp, startblk, blocks, buffer, &actual_len);
if (res == MSD_RESULT_DISCONNECTED) {
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_FAILED) {
//TODO: request sense, and act appropriately
uerr("\tWRITE (10): Command Failed");
_requestsense(lunp);
} else if (res == MSD_RESULT_TRANSPORT_ERROR) {
//retry?
goto exit;
} else if (res.cres == MSD_COMMANDRESULT_PHASE_ERROR) {
//TODO: Do reset, etc.
uerr("\tWRITE (10): Command Phase Error");
} else if (res == MSD_RESULT_FAILED) {
//retry?
goto exit;
}
n -= blocks;
@ -936,4 +1001,13 @@ void usbhmsdObjectInit(USBHMassStorageDriver *msdp) {
osalMutexObjectInit(&msdp->mtx);
}
void usbhmsdInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHMSD_MAX_INSTANCES; i++) {
usbhmsdObjectInit(&USBHMSD[i]);
}
for (i = 0; i < HAL_USBHMSD_MAX_LUNS; i++) {
usbhmsdLUNObjectInit(&MSBLKD[i]);
}
}
#endif

View File

@ -1,6 +1,6 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Copyright (C) 2015 Diego Ismirlian, TISA, (dismirlian (at) google's mail)
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
Copyright (C) 2015..2017 Diego Ismirlian, (dismirlian (at) google's mail)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -13,10 +13,9 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
*/
#include "hal.h"
#include "hal_usbh.h"
#if HAL_USBH_USE_UVC
@ -28,6 +27,10 @@
#error "USBHUVC needs HAL_USBH_USE_IAD"
#endif
#include "usbh/dev/uvc.h"
#include "usbh/internal.h"
#include <string.h>
#if USBHUVC_DEBUG_ENABLE_TRACE
#define udbgf(f, ...) usbDbgPrintf(f, ##__VA_ARGS__)
#define udbg(f, ...) usbDbgPuts(f, ##__VA_ARGS__)
@ -61,6 +64,9 @@
#endif
USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES];
static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev,
const uint8_t *descriptor, uint16_t rem);
static void uvc_unload(usbh_baseclassdriver_t *drv);
@ -73,16 +79,653 @@ const usbh_classdriverinfo_t usbhuvcClassDriverInfo = {
0x0e, 0x03, 0x00, "UVC", &class_driver_vmt
};
static bool _request(USBHUVCDriver *uvcdp,
uint8_t bRequest, uint8_t entity, uint8_t control,
uint16_t wLength, uint8_t *data, uint8_t interf) {
usbh_urbstatus_t res;
if (bRequest & 0x80) {
res = usbhControlRequest(uvcdp->dev,
USBH_REQTYPE_CLASSIN(USBH_REQTYPE_RECIP_INTERFACE),
bRequest,
((control) << 8),
(interf) | ((entity) << 8),
wLength, data);
} else {
res = usbhControlRequest(uvcdp->dev,
USBH_REQTYPE_CLASSOUT(USBH_REQTYPE_RECIP_INTERFACE),
bRequest,
((control) << 8),
(interf) | ((entity) << 8),
wLength, data);
}
if (res != USBH_URBSTATUS_OK)
return HAL_FAILED;
return HAL_SUCCESS;
}
bool usbhuvcVCRequest(USBHUVCDriver *uvcdp,
uint8_t bRequest, uint8_t entity, uint8_t control,
uint16_t wLength, uint8_t *data) {
return _request(uvcdp, bRequest, entity, control, wLength, data, if_get(&uvcdp->ivc)->bInterfaceNumber);
}
bool usbhuvcVSRequest(USBHUVCDriver *uvcdp,
uint8_t bRequest, uint8_t control,
uint16_t wLength, uint8_t *data) {
return _request(uvcdp, bRequest, 0, control, wLength, data, if_get(&uvcdp->ivs)->bInterfaceNumber);
}
static bool _set_vs_alternate(USBHUVCDriver *uvcdp, uint16_t min_ep_size) {
if (min_ep_size == 0) {
uinfo("Selecting Alternate setting 0");
return usbhStdReqSetInterface(uvcdp->dev, if_get(&uvcdp->ivs)->bInterfaceNumber, 0);
}
if_iterator_t iif = uvcdp->ivs;
generic_iterator_t iep;
const usbh_endpoint_descriptor_t *ep = NULL;
uint8_t alt = 0;
uint16_t sz = 0xffff;
uinfof("Searching alternate setting with min_ep_size=%d", min_ep_size);
for (; iif.valid; if_iter_next(&iif)) {
const usbh_interface_descriptor_t *const ifdesc = if_get(&iif);
if ((ifdesc->bInterfaceClass != UVC_CC_VIDEO)
|| (ifdesc->bInterfaceSubClass != UVC_SC_VIDEOSTREAMING))
continue;
uinfof("\tScanning alternate setting=%d", ifdesc->bAlternateSetting);
if (ifdesc->bNumEndpoints == 0)
continue;
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if (((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_ISO)
&& ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) {
uinfof("\t Endpoint wMaxPacketSize = %d", epdesc->wMaxPacketSize);
if (epdesc->wMaxPacketSize >= min_ep_size) {
if (epdesc->wMaxPacketSize < sz) {
uinfo("\t Found new optimal alternate setting");
sz = epdesc->wMaxPacketSize;
alt = ifdesc->bAlternateSetting;
ep = epdesc;
}
}
}
}
}
if (ep && alt) {
uinfof("\tSelecting Alternate setting %d", alt);
if (usbhStdReqSetInterface(uvcdp->dev, if_get(&uvcdp->ivs)->bInterfaceNumber, alt) == HAL_SUCCESS) {
usbhEPObjectInit(&uvcdp->ep_iso, uvcdp->dev, ep);
usbhEPSetName(&uvcdp->ep_iso, "UVC[ISO ]");
return HAL_SUCCESS;
}
}
return HAL_FAILED;
}
#if USBH_DEBUG_ENABLE && USBHUVC_DEBUG_ENABLE_INFO
void usbhuvcPrintProbeCommit(const usbh_uvc_ctrl_vs_probecommit_data_t *pc) {
//uinfof("UVC: probe/commit data:");
uinfof("\tbmHint=%04x", pc->bmHint);
uinfof("\tbFormatIndex=%d, bFrameIndex=%d, dwFrameInterval=%u",
pc->bFormatIndex, pc->bFrameIndex, pc->dwFrameInterval);
uinfof("\twKeyFrameRate=%d, wPFrameRate=%d, wCompQuality=%u, wCompWindowSize=%u",
pc->wKeyFrameRate, pc->wPFrameRate, pc->wCompQuality, pc->wCompWindowSize);
uinfof("\twDelay=%d", pc->wDelay);
uinfof("\tdwMaxVideoFrameSize=%u", pc->dwMaxVideoFrameSize);
uinfof("\tdwMaxPayloadTransferSize=%u", pc->dwMaxPayloadTransferSize);
/* uinfof("\tdwClockFrequency=%u", pc->dwClockFrequency);
uinfof("\tbmFramingInfo=%02x", pc->bmFramingInfo);
uinfof("\tbPreferedVersion=%d, bMinVersion=%d, bMaxVersion=%d",
pc->bPreferedVersion, pc->bMinVersion, pc->bMaxVersion); */
}
#endif
static void _post(USBHUVCDriver *uvcdp, usbh_urb_t *urb, memory_pool_t *mp, uint16_t type) {
usbhuvc_message_base_t *const msg = (usbhuvc_message_base_t *)urb->buff - 1;
msg->timestamp = osalOsGetSystemTimeX();
usbhuvc_message_base_t *const new_msg = (usbhuvc_message_base_t *)chPoolAllocI(mp);
if (new_msg != NULL) {
/* allocated the new buffer, now try to post the message to the mailbox */
if (chMBPostI(&uvcdp->mb, (msg_t)msg) == MSG_OK) {
/* everything OK, complete the missing fields */
msg->type = type;
msg->length = urb->actualLength;
/* change the URB's buffer to the newly allocated one */
urb->buff = (uint8_t *)(new_msg + 1);
} else {
/* couldn't post the message, free the newly allocated buffer */
uerr("UVC: error, mailbox overrun");
chPoolFreeI(&uvcdp->mp_status, new_msg);
}
} else {
uerrf("UVC: error, %s pool overrun", mp == &uvcdp->mp_data ? "data" : "status");
}
}
static void _cb_int(usbh_urb_t *urb) {
USBHUVCDriver *uvcdp = (USBHUVCDriver *)urb->userData;
switch (urb->status) {
case USBH_URBSTATUS_OK:
if (urb->actualLength >= 2) {
_post(uvcdp, urb, &uvcdp->mp_status, USBHUVC_MESSAGETYPE_STATUS);
} else {
uerrf("UVC: INT IN, actualLength=%d", urb->actualLength);
}
break;
case USBH_URBSTATUS_TIMEOUT: /* the device NAKed */
udbg("UVC: INT IN no info");
break;
case USBH_URBSTATUS_DISCONNECTED:
case USBH_URBSTATUS_CANCELLED:
uwarn("UVC: INT IN status = DISCONNECTED/CANCELLED, aborting");
return;
default:
uerrf("UVC: INT IN error, unexpected status = %d", urb->status);
break;
}
usbhURBObjectResetI(urb);
usbhURBSubmitI(urb);
}
static void _cb_iso(usbh_urb_t *urb) {
USBHUVCDriver *uvcdp = (USBHUVCDriver *)urb->userData;
if ((urb->status == USBH_URBSTATUS_DISCONNECTED)
|| (urb->status == USBH_URBSTATUS_CANCELLED)) {
uwarn("UVC: ISO IN status = DISCONNECTED/CANCELLED, aborting");
return;
}
if (urb->status != USBH_URBSTATUS_OK) {
uerrf("UVC: ISO IN error, unexpected status = %d", urb->status);
} else if (urb->actualLength >= 2) {
const uint8_t *const buff = (const uint8_t *)urb->buff;
if (buff[0] < 2) {
uerrf("UVC: ISO IN, bHeaderLength=%d", buff[0]);
} else if (buff[0] > urb->actualLength) {
uerrf("UVC: ISO IN, bHeaderLength=%d > actualLength=%d", buff[0], urb->actualLength);
} else {
udbgf("UVC: ISO IN len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d",
urb->actualLength,
buff[0],
buff[1] & UVC_HDR_FID,
buff[1] & UVC_HDR_EOF,
buff[1] & UVC_HDR_ERR,
buff[1] & UVC_HDR_EOH);
if ((urb->actualLength > buff[0])
|| (buff[1] & (UVC_HDR_EOF | UVC_HDR_ERR))) {
_post(uvcdp, urb, &uvcdp->mp_data, USBHUVC_MESSAGETYPE_DATA);
} else {
udbgf("UVC: ISO IN skip: len=%d, hdr=%d, FID=%d, EOF=%d, ERR=%d, EOH=%d",
urb->actualLength,
buff[0],
buff[1] & UVC_HDR_FID,
buff[1] & UVC_HDR_EOF,
buff[1] & UVC_HDR_ERR,
buff[1] & UVC_HDR_EOH);
}
}
} else if (urb->actualLength > 0) {
uerrf("UVC: ISO IN, actualLength=%d", urb->actualLength);
}
usbhURBObjectResetI(urb);
usbhURBSubmitI(urb);
}
bool usbhuvcStreamStart(USBHUVCDriver *uvcdp, uint16_t min_ep_sz) {
bool ret = HAL_FAILED;
osalSysLock();
osalDbgCheck(uvcdp && (uvcdp->state != USBHUVC_STATE_UNINITIALIZED) &&
(uvcdp->state != USBHUVC_STATE_BUSY));
if (uvcdp->state == USBHUVC_STATE_STREAMING) {
osalSysUnlock();
return HAL_SUCCESS;
}
if (uvcdp->state != USBHUVC_STATE_READY) {
osalSysUnlock();
return HAL_FAILED;
}
uvcdp->state = USBHUVC_STATE_BUSY;
osalSysUnlock();
//set the alternate setting
if (_set_vs_alternate(uvcdp, min_ep_sz) != HAL_SUCCESS)
goto exit;
//reserve working RAM
uint32_t datapackets;
uint32_t data_sz = (uvcdp->ep_iso.wMaxPacketSize + sizeof(usbhuvc_message_data_t) + 3) & ~3;
datapackets = HAL_USBHUVC_WORK_RAM_SIZE / data_sz;
if (datapackets == 0) {
uerr("Not enough work RAM");
goto failed;
}
uint32_t workramsz = datapackets * data_sz;
uinfof("Reserving %u bytes of RAM (%d data packets of %d bytes)", workramsz, datapackets, data_sz);
if (datapackets > (HAL_USBHUVC_MAX_MAILBOX_SZ - HAL_USBHUVC_STATUS_PACKETS_COUNT)) {
uwarn("Mailbox may overflow, use a larger HAL_USBHUVC_MAX_MAILBOX_SZ. UVC will under-utilize the assigned work RAM.");
}
chMBResumeX(&uvcdp->mb);
uvcdp->mp_data_buffer = chHeapAlloc(NULL, workramsz);
if (uvcdp->mp_data_buffer == NULL) {
uerr("Couldn't reserve RAM");
goto failed;
}
//initialize the mempool
const uint8_t *elem = (const uint8_t *)uvcdp->mp_data_buffer;
chPoolObjectInit(&uvcdp->mp_data, data_sz, NULL);
while (datapackets--) {
chPoolFree(&uvcdp->mp_data, (void *)elem);
elem += data_sz;
}
//open the endpoint
usbhEPOpen(&uvcdp->ep_iso);
//allocate 1 buffer and submit the first transfer
usbhuvc_message_data_t *const msg = (usbhuvc_message_data_t *)chPoolAlloc(&uvcdp->mp_data);
osalDbgCheck(msg);
usbhURBObjectInit(&uvcdp->urb_iso, &uvcdp->ep_iso, _cb_iso, uvcdp, msg->data, uvcdp->ep_iso.wMaxPacketSize);
osalSysLock();
usbhURBSubmitI(&uvcdp->urb_iso);
osalOsRescheduleS();
osalSysUnlock();
ret = HAL_SUCCESS;
goto exit;
failed:
_set_vs_alternate(uvcdp, 0);
if (uvcdp->mp_data_buffer)
chHeapFree(uvcdp->mp_data_buffer);
exit:
osalSysLock();
if (ret == HAL_SUCCESS)
uvcdp->state = USBHUVC_STATE_STREAMING;
else
uvcdp->state = USBHUVC_STATE_READY;
osalSysUnlock();
return ret;
}
bool usbhuvcStreamStop(USBHUVCDriver *uvcdp) {
osalSysLock();
osalDbgCheck(uvcdp && (uvcdp->state != USBHUVC_STATE_UNINITIALIZED) &&
(uvcdp->state != USBHUVC_STATE_BUSY));
if (uvcdp->state != USBHUVC_STATE_STREAMING) {
osalSysUnlock();
return HAL_SUCCESS;
}
uvcdp->state = USBHUVC_STATE_BUSY;
//close the ISO endpoint
usbhEPCloseS(&uvcdp->ep_iso);
//purge the mailbox
chMBResetI(&uvcdp->mb); //TODO: the status messages are lost!!
chMtxLockS(&uvcdp->mtx);
osalSysUnlock();
//free the working memory
chHeapFree(uvcdp->mp_data_buffer);
uvcdp->mp_data_buffer = 0;
//set alternate setting to 0
_set_vs_alternate(uvcdp, 0);
osalSysLock();
uvcdp->state = USBHUVC_STATE_READY;
chMtxUnlockS(&uvcdp->mtx);
osalSysUnlock();
return HAL_SUCCESS;
}
bool usbhuvcFindVSDescriptor(USBHUVCDriver *uvcdp,
generic_iterator_t *ics,
uint8_t bDescriptorSubtype,
bool start) {
if (start)
cs_iter_init(ics, (generic_iterator_t *)&uvcdp->ivs);
else
cs_iter_next(ics);
for (; ics->valid; cs_iter_next(ics)) {
if (ics->curr[1] != UVC_CS_INTERFACE)
break;
if (ics->curr[2] == bDescriptorSubtype)
return HAL_SUCCESS;
if (!start)
break;
}
return HAL_FAILED;
}
void usbhuvcResetPC(USBHUVCDriver *uvcdp) {
memset(&uvcdp->pc, 0, sizeof(uvcdp->pc));
}
bool usbhuvcProbe(USBHUVCDriver *uvcdp) {
// memset(&uvcdp->pc_min, 0, sizeof(uvcdp->pc_min));
// memset(&uvcdp->pc_max, 0, sizeof(uvcdp->pc_max));
if (usbhuvcVSRequest(uvcdp, UVC_SET_CUR, UVC_CTRL_VS_PROBE_CONTROL, sizeof(uvcdp->pc), (uint8_t *)&uvcdp->pc) != HAL_SUCCESS)
return HAL_FAILED;
if (usbhuvcVSRequest(uvcdp, UVC_GET_CUR, UVC_CTRL_VS_PROBE_CONTROL, sizeof(uvcdp->pc), (uint8_t *)&uvcdp->pc) != HAL_SUCCESS)
return HAL_FAILED;
if (usbhuvcVSRequest(uvcdp, UVC_GET_MAX, UVC_CTRL_VS_PROBE_CONTROL, sizeof(uvcdp->pc_max), (uint8_t *)&uvcdp->pc_max) != HAL_SUCCESS)
return HAL_FAILED;
if (usbhuvcVSRequest(uvcdp, UVC_GET_MIN, UVC_CTRL_VS_PROBE_CONTROL, sizeof(uvcdp->pc_min), (uint8_t *)&uvcdp->pc_min) != HAL_SUCCESS)
return HAL_FAILED;
return HAL_SUCCESS;
}
bool usbhuvcCommit(USBHUVCDriver *uvcdp) {
if (usbhuvcVSRequest(uvcdp, UVC_SET_CUR, UVC_CTRL_VS_COMMIT_CONTROL, sizeof(uvcdp->pc), (uint8_t *)&uvcdp->pc) != HAL_SUCCESS)
return HAL_FAILED;
osalSysLock();
if (uvcdp->state == USBHUVC_STATE_ACTIVE)
uvcdp->state = USBHUVC_STATE_READY;
osalSysUnlock();
return HAL_SUCCESS;
}
uint32_t usbhuvcEstimateRequiredEPSize(USBHUVCDriver *uvcdp, const uint8_t *formatdesc,
const uint8_t *framedesc, uint32_t dwFrameInterval) {
osalDbgCheck(framedesc);
osalDbgCheck(framedesc[0] > 3);
osalDbgCheck(framedesc[1] == UVC_CS_INTERFACE);
osalDbgCheck(formatdesc);
osalDbgCheck(formatdesc[0] > 3);
osalDbgCheck(formatdesc[1] == UVC_CS_INTERFACE);
uint16_t w, h, div, mul;
uint8_t bpp;
switch (framedesc[2]) {
case UVC_VS_FRAME_MJPEG: {
const usbh_uvc_frame_mjpeg_t *frame = (const usbh_uvc_frame_mjpeg_t *)framedesc;
//const usbh_uvc_format_mjpeg_t *fmt = (const usbh_uvc_format_mjpeg_t *)formatdesc;
w = frame->wWidth;
h = frame->wHeight;
bpp = 16; //TODO: check this!!
mul = 1;
div = 5; //TODO: check this estimate
} break;
case UVC_VS_FRAME_UNCOMPRESSED: {
const usbh_uvc_frame_uncompressed_t *frame = (const usbh_uvc_frame_uncompressed_t *)framedesc;
const usbh_uvc_format_uncompressed *fmt = (const usbh_uvc_format_uncompressed *)formatdesc;
w = frame->wWidth;
h = frame->wHeight;
bpp = fmt->bBitsPerPixel;
mul = div = 1;
} break;
default:
uwarn("Unsupported format");
return 0xffffffff;
}
uint32_t sz = w * h / 8 * bpp;
sz *= 10000000UL / dwFrameInterval;
sz /= 1000;
if (uvcdp->dev->speed == USBH_DEVSPEED_HIGH)
div *= 8;
return (sz * mul) / div + 12;
}
void usbhuvcObjectInit(USBHUVCDriver *uvcdp) {
osalDbgCheck(uvcdp != NULL);
memset(uvcdp, 0, sizeof(*uvcdp));
uvcdp->info = &usbhuvcClassDriverInfo;
chMBObjectInit(&uvcdp->mb, uvcdp->mb_buff, HAL_USBHUVC_MAX_MAILBOX_SZ);
chMtxObjectInit(&uvcdp->mtx);
uvcdp->state = USBHUVC_STATE_STOP;
}
static usbh_baseclassdriver_t *uvc_load(usbh_device_t *dev, const uint8_t *descriptor, uint16_t rem) {
(void)dev;
(void)descriptor;
(void)rem;
USBHUVCDriver *uvcdp;
uint8_t i;
if (descriptor[1] != USBH_DT_INTERFACE_ASSOCIATION)
return NULL;
/* alloc driver */
for (i = 0; i < HAL_USBHUVC_MAX_INSTANCES; i++) {
if (USBHUVCD[i].dev == NULL) {
uvcdp = &USBHUVCD[i];
goto alloc_ok;
}
}
uwarn("Can't alloc UVC driver");
/* can't alloc */
return NULL;
alloc_ok:
/* initialize the driver's variables */
uvcdp->ivc.curr = uvcdp->ivs.curr = NULL;
usbhEPSetName(&dev->ctrl, "UVC[CTRL]");
const usbh_ia_descriptor_t *iad = (const usbh_ia_descriptor_t *)descriptor;
if_iterator_t iif;
generic_iterator_t ics;
generic_iterator_t iep;
iif.iad = iad;
iif.curr = descriptor;
iif.rem = rem;
for (if_iter_next(&iif); iif.valid; if_iter_next(&iif)) {
if (iif.iad != iad) break;
const usbh_interface_descriptor_t *const ifdesc = if_get(&iif);
if (ifdesc->bInterfaceClass != UVC_CC_VIDEO) {
uwarnf("Skipping Interface %d (class != UVC_CC_VIDEO)",
ifdesc->bInterfaceNumber);
continue;
}
uinfof("Interface %d, Alt=%d, Class=UVC_CC_VIDEO, Subclass=%02x",
ifdesc->bInterfaceNumber,
ifdesc->bAlternateSetting,
ifdesc->bInterfaceSubClass);
switch (ifdesc->bInterfaceSubClass) {
case UVC_SC_VIDEOCONTROL:
if (uvcdp->ivc.curr == NULL) {
uvcdp->ivc = iif;
}
for (cs_iter_init(&ics, (generic_iterator_t *)&iif); ics.valid; cs_iter_next(&ics)) {
if (ics.curr[1] != UVC_CS_INTERFACE) {
uwarnf("Unknown descriptor=%02X", ics.curr[1]);
continue;
}
switch (ics.curr[2]) {
case UVC_VC_HEADER:
uinfo(" VC_HEADER"); break;
case UVC_VC_INPUT_TERMINAL:
uinfof(" VC_INPUT_TERMINAL, ID=%d", ics.curr[3]); break;
case UVC_VC_OUTPUT_TERMINAL:
uinfof(" VC_OUTPUT_TERMINAL, ID=%d", ics.curr[3]); break;
case UVC_VC_SELECTOR_UNIT:
uinfof(" VC_SELECTOR_UNIT, ID=%d", ics.curr[3]); break;
case UVC_VC_PROCESSING_UNIT:
uinfof(" VC_PROCESSING_UNIT, ID=%d", ics.curr[3]); break;
case UVC_VC_EXTENSION_UNIT:
uinfof(" VC_EXTENSION_UNIT, ID=%d", ics.curr[3]); break;
default:
uwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]);
break;
}
}
break;
case UVC_SC_VIDEOSTREAMING:
if (uvcdp->ivs.curr == NULL) {
uvcdp->ivs = iif;
}
for (cs_iter_init(&ics, (generic_iterator_t *)&iif); ics.valid; cs_iter_next(&ics)) {
if (ics.curr[1] != UVC_CS_INTERFACE) {
uwarnf("Unknown descriptor=%02X", ics.curr[1]);
continue;
}
switch (ics.curr[2]) {
case UVC_VS_INPUT_HEADER:
uinfo(" VS_INPUT_HEADER"); break;
case UVC_VS_OUTPUT_HEADER:
uinfo(" VS_OUTPUT_HEADER"); break;
case UVC_VS_STILL_IMAGE_FRAME:
uinfo(" VS_STILL_IMAGE_FRAME"); break;
case UVC_VS_FORMAT_UNCOMPRESSED:
uinfof(" VS_FORMAT_UNCOMPRESSED, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FORMAT_MPEG2TS:
uinfof(" VS_FORMAT_MPEG2TS, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FORMAT_DV:
uinfof(" VS_FORMAT_DV, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FORMAT_MJPEG:
uinfof(" VS_FORMAT_MJPEG, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FORMAT_FRAME_BASED:
uinfof(" VS_FORMAT_FRAME_BASED, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FORMAT_STREAM_BASED:
uinfof(" VS_FORMAT_STREAM_BASED, bFormatIndex=%d", ics.curr[3]); break;
case UVC_VS_FRAME_UNCOMPRESSED:
uinfof(" VS_FRAME_UNCOMPRESSED, bFrameIndex=%d", ics.curr[3]); break;
case UVC_VS_FRAME_MJPEG:
uinfof(" VS_FRAME_MJPEG, bFrameIndex=%d", ics.curr[3]); break;
case UVC_VS_FRAME_FRAME_BASED:
uinfof(" VS_FRAME_FRAME_BASED, bFrameIndex=%d", ics.curr[3]); break;
case UVC_VS_COLOR_FORMAT:
uinfo(" VS_COLOR_FORMAT"); break;
default:
uwarnf("Unknown video bDescriptorSubtype=%02x", ics.curr[2]);
break;
}
}
break;
default:
uwarnf("Unknown video bInterfaceSubClass=%02x", ifdesc->bInterfaceSubClass);
break;
}
for (ep_iter_init(&iep, &iif); iep.valid; ep_iter_next(&iep)) {
const usbh_endpoint_descriptor_t *const epdesc = ep_get(&iep);
if ((ifdesc->bInterfaceSubClass == UVC_SC_VIDEOCONTROL)
&& ((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_INT)
&& ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) {
/* found VC interrupt endpoint */
uinfof(" VC Interrupt endpoint; %02x, bInterval=%d",
epdesc->bEndpointAddress, epdesc->bInterval);
usbhEPObjectInit(&uvcdp->ep_int, dev, epdesc);
usbhEPSetName(&uvcdp->ep_int, "UVC[INT ]");
} else if ((ifdesc->bInterfaceSubClass == UVC_SC_VIDEOSTREAMING)
&& ((epdesc->bmAttributes & 0x03) == USBH_EPTYPE_ISO)
&& ((epdesc->bEndpointAddress & 0x80) == USBH_EPDIR_IN)) {
/* found VS isochronous endpoint */
uinfof(" VS Isochronous endpoint; %02x, bInterval=%d, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bInterval, epdesc->bmAttributes);
} else {
/* unknown EP */
uwarnf(" <unknown endpoint>, bEndpointAddress=%02x, bmAttributes=%02x",
epdesc->bEndpointAddress, epdesc->bmAttributes);
}
for (cs_iter_init(&ics, &iep); ics.valid; cs_iter_next(&ics)) {
uinfof(" CS_ENDPOINT bLength=%d, bDescriptorType=%02X",
ics.curr[0], ics.curr[1]);
}
}
}
if ((uvcdp->ivc.curr == NULL) || (uvcdp->ivs.curr == NULL)) {
return NULL;
}
// uvcdp->dev = dev;
_set_vs_alternate(uvcdp, 0);
/* initialize the INT endpoint */
chPoolObjectInit(&uvcdp->mp_status, sizeof(usbhuvc_message_status_t), NULL);
for(i = 0; i < HAL_USBHUVC_STATUS_PACKETS_COUNT; i++)
chPoolFree(&uvcdp->mp_status, &uvcdp->mp_status_buffer[i]);
usbhEPOpen(&uvcdp->ep_int);
usbhuvc_message_status_t *const msg = (usbhuvc_message_status_t *)chPoolAlloc(&uvcdp->mp_status);
osalDbgCheck(msg);
usbhURBObjectInit(&uvcdp->urb_int, &uvcdp->ep_int, _cb_int, uvcdp, msg->data, USBHUVC_MAX_STATUS_PACKET_SZ);
osalSysLock();
usbhURBSubmitI(&uvcdp->urb_int);
uvcdp->state = USBHUVC_STATE_ACTIVE;
osalOsRescheduleS();
osalSysUnlock();
dev->keepFullCfgDesc++;
return (usbh_baseclassdriver_t *)uvcdp;
}
static void uvc_unload(usbh_baseclassdriver_t *drv) {
(void)drv;
USBHUVCDriver *const uvcdp = (USBHUVCDriver *)drv;
usbhuvcStreamStop(uvcdp);
usbhEPClose(&uvcdp->ep_int);
//TODO: free
if (drv->dev->keepFullCfgDesc)
drv->dev->keepFullCfgDesc--;
osalSysLock();
uvcdp->state = USBHUVC_STATE_STOP;
osalSysUnlock();
}
void usbhuvcInit(void) {
uint8_t i;
for (i = 0; i < HAL_USBHUVC_MAX_INSTANCES; i++) {
usbhuvcObjectInit(&USBHUVCD[i]);
}
}
#endif

View File

@ -0,0 +1,7 @@
# FATFS files.
FATFSSRC = ${CHIBIOS_CONTRIB}/os/various/fatfs_bindings/fatfs_diskio.c \
${CHIBIOS}/os/various/fatfs_bindings/fatfs_syscall.c \
${CHIBIOS}/ext/fatfs/src/ff.c \
${CHIBIOS}/ext/fatfs/src/option/unicode.c
FATFSINC = ${CHIBIOS}/ext/fatfs/src

View File

@ -0,0 +1,320 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "hal.h"
#include "ffconf.h"
#include "diskio.h"
#include "usbh/dev/msd.h"
#if HAL_USE_MMC_SPI && HAL_USE_SDC
#error "cannot specify both MMC_SPI and SDC drivers"
#endif
#if HAL_USE_MMC_SPI
extern MMCDriver MMCD1;
#elif HAL_USE_SDC
extern SDCDriver SDCD1;
#elif HAL_USBH_USE_MSD
#else
#error "MMC_SPI, SDC or USBH_MSD driver must be specified"
#endif
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#if HAL_USE_MMC_SPI
#define MMC 0
#endif
#if HAL_USE_SDC
#define SDC 0
#endif
#if HAL_USBH_USE_MSD
#if defined(MMC) || defined(SDC)
#define MSDLUN0 1
#else
#define MSDLUN0 0
#endif
#endif
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
#if HAL_USE_MMC_SPI
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
return stat;
#elif HAL_USE_SDC
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
return stat;
#endif
#if HAL_USBH_USE_MSD
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
#endif
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
#if HAL_USE_MMC_SPI
case MMC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MMCD1) != BLK_READY)
stat |= STA_NOINIT;
if (mmcIsWriteProtected(&MMCD1))
stat |= STA_PROTECT;
return stat;
#elif HAL_USE_SDC
case SDC:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&SDCD1) != BLK_READY)
stat |= STA_NOINIT;
if (sdcIsWriteProtected(&SDCD1))
stat |= STA_PROTECT;
return stat;
#endif
#if HAL_USBH_USE_MSD
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
#endif
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..255) */
)
{
switch (pdrv) {
#if HAL_USE_MMC_SPI
case MMC:
if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcStartSequentialRead(&MMCD1, sector))
return RES_ERROR;
while (count > 0) {
if (mmcSequentialRead(&MMCD1, buff))
return RES_ERROR;
buff += MMCSD_BLOCK_SIZE;
count--;
}
if (mmcStopSequentialRead(&MMCD1))
return RES_ERROR;
return RES_OK;
#elif HAL_USE_SDC
case SDC:
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcRead(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
#if HAL_USBH_USE_MSD
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNRead(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..255) */
)
{
switch (pdrv) {
#if HAL_USE_MMC_SPI
case MMC:
if (blkGetDriverState(&MMCD1) != BLK_READY)
return RES_NOTRDY;
if (mmcIsWriteProtected(&MMCD1))
return RES_WRPRT;
if (mmcStartSequentialWrite(&MMCD1, sector))
return RES_ERROR;
while (count > 0) {
if (mmcSequentialWrite(&MMCD1, buff))
return RES_ERROR;
buff += MMCSD_BLOCK_SIZE;
count--;
}
if (mmcStopSequentialWrite(&MMCD1))
return RES_ERROR;
return RES_OK;
#elif HAL_USE_SDC
case SDC:
if (blkGetDriverState(&SDCD1) != BLK_READY)
return RES_NOTRDY;
if (sdcWrite(&SDCD1, sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
#if HAL_USBH_USE_MSD
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNWrite(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
#endif
}
return RES_PARERR;
}
#endif /* _USE_WRITE */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (pdrv) {
#if HAL_USE_MMC_SPI
case MMC:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MMCSD_BLOCK_SIZE;
return RES_OK;
#if _USE_ERASE
case CTRL_ERASE_SECTOR:
mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
return RES_OK;
#endif
default:
return RES_PARERR;
}
#elif HAL_USE_SDC
case SDC:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD *)buff) = mmcsdGetCardCapacity(&SDCD1);
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MMCSD_BLOCK_SIZE;
return RES_OK;
case GET_BLOCK_SIZE:
*((DWORD *)buff) = 256; /* 512b blocks in one erase block */
return RES_OK;
#if _USE_ERASE
case CTRL_ERASE_SECTOR:
sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
return RES_OK;
#endif
default:
return RES_PARERR;
}
#endif
#if HAL_USBH_USE_MSD
case MSDLUN0:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD *)buff) = MSBLKD[0].info.blk_num;
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MSBLKD[0].info.blk_size;
return RES_OK;
#if _USE_ERASE
#error "unimplemented yet!"
// case CTRL_ERASE_SECTOR:
// ....
// return RES_OK;
#endif
default:
return RES_PARERR;
}
#endif
}
return RES_PARERR;
}
#endif /* _USE_IOCTL */
DWORD get_fattime(void) {
#if HAL_USE_RTC
RTCDateTime timespec;
rtcGetTime(&RTCD1, &timespec);
return rtcConvertDateTimeToFAT(&timespec);
#else
return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
#endif
}

View File

@ -18,7 +18,7 @@
<folderInfo id="0.1003150841." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.748316353" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.748316353.81353447" name=""/>
<builder id="org.eclipse.cdt.build.core.settings.default.builder.1044649944" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<builder arguments="-j8" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.1044649944" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.883535580" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.97391908" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.133315636" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
@ -39,11 +39,26 @@
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="STM32F4xx-USB_HOST.null.1232072164" name="STM32F4xx-USB_HOST"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/STM32F4xx-USB_HOST"/>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="0.1003150841">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath="D:/proyectos/ChibiOS-contrib-devel/ChibiOS-Contrib/testhal/STM32/STM32F4xx/USB_HOST/build/ch.elf"/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;" command="arm-none-eabi-gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View File

@ -24,4 +24,16 @@
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>ChibiOS-Contrib-os</name>
<type>2</type>
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/ChibiOS-contrib/os</locationURI>
</link>
<link>
<name>ChibiOS-RT-os</name>
<type>2</type>
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/ChibiOS-RT/os</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@ -5,7 +5,7 @@
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -Os -ggdb -fomit-frame-pointer -falign-functions=16
USE_OPT = -Og -ggdb3 -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
@ -30,7 +30,7 @@ endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
USE_LTO = no
endif
# If enabled, this option allows to compile the application in THUMB mode.
@ -89,7 +89,7 @@ PROJECT = ch
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Startup files.
include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk
# HAL-OSAL files (optional).
include $(CHIBIOS_CONTRIB)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/STM32/STM32F4xx/platform.mk
@ -97,12 +97,15 @@ include $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
include $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
include $(CHIBIOS)/test/rt/test.mk
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
include $(CHIBIOS)/os/various/shell/shell.mk
include $(CHIBIOS)/os/various/fatfs_bindings/fatfs.mk
include $(CHIBIOS_CONTRIB)/os/various/fatfs_bindings/fatfs.mk
STREAMSSRC = $(CHIBIOS)/os/hal/lib/streams/chprintf.c $(CHIBIOS)/os/hal/lib/streams/memstreams.c
STREAMSINC = $(CHIBIOS)/os/hal/lib/streams/
SHELLSRC = $(CHIBIOS)/os/various/shell.c
SHELLINC = $(CHIBIOS)/os/various/
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/STM32F407xG.ld
@ -147,8 +150,7 @@ TCSRC =
TCPPSRC =
# List ASM source files here
ASMSRC =
ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(CHIBIOS)/os/license \
$(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
@ -222,5 +224,5 @@ ULIBS =
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -1,80 +0,0 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,143 +0,0 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "hal.h"
#include "ffconf.h"
#include "diskio.h"
#include "usbh/dev/msd.h"
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define MSDLUN0 0
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
switch (pdrv) {
case MSDLUN0:
stat = 0;
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
stat |= STA_NOINIT;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..255) */
)
{
switch (pdrv) {
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNRead(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..255) */
)
{
switch (pdrv) {
case MSDLUN0:
/* It is initialized externally, just reads the status.*/
if (blkGetDriverState(&MSBLKD[0]) != BLK_READY)
return RES_NOTRDY;
if (usbhmsdLUNWrite(&MSBLKD[0], sector, buff, count))
return RES_ERROR;
return RES_OK;
}
return RES_PARERR;
}
#endif /* _USE_WRITE */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (pdrv) {
case MSDLUN0:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*((DWORD *)buff) = MSBLKD[0].info.blk_num;
return RES_OK;
case GET_SECTOR_SIZE:
*((WORD *)buff) = MSBLKD[0].info.blk_size;
return RES_OK;
default:
return RES_PARERR;
}
}
return RES_PARERR;
}
#endif /* _USE_IOCTL */
DWORD get_fattime(void) {
return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
}

File diff suppressed because it is too large Load Diff

View File

@ -1,342 +0,0 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.10b (C)ChaN, 2014
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2014, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 8051 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
BYTE n_fats; /* Number of FAT copies (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
DWORD fsize; /* Sectors per FAT */
DWORD volbase; /* Volume start sector */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
BYTE flag; /* Status flags */
BYTE err; /* Abort flag (error code) */
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
#endif
#if _FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;
/* File status structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
FRESULT f_truncate (FIL* fp); /* Truncate file */
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek feature */
#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

View File

@ -8,7 +8,6 @@
#ifndef _FFCONF
#define _FFCONF 8051 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
/---------------------------------------------------------------------------*/
@ -92,7 +91,7 @@
/ 1 - ASCII (Valid for only non-LFN configuration) */
#define _USE_LFN 3 /* 0 to 3 */
#define _USE_LFN 0 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN feature.
/

View File

@ -91,13 +91,13 @@
#define HAL_USBH_DEVICE_ADDRESS_STABILIZATION 20
/* MSD */
#define HAL_USBH_USE_MSD 1
#define HAL_USBH_USE_MSD TRUE
#define HAL_USBHMSD_MAX_LUNS 1
#define HAL_USBHMSD_MAX_INSTANCES 1
/* IAD */
#define HAL_USBH_USE_FTDI 1
/* FTDI */
#define HAL_USBH_USE_FTDI TRUE
#define HAL_USBHFTDI_MAX_PORTS 1
#define HAL_USBHFTDI_MAX_INSTANCES 1
@ -107,61 +107,85 @@
#define HAL_USBHFTDI_DEFAULT_XON 0x11
#define HAL_USBHFTDI_DEFAULT_XOFF 0x13
/* AOA */
#define HAL_USBH_USE_AOA TRUE
/* IAD */
#define HAL_USBH_USE_IAD 0
#define HAL_USBHAOA_MAX_INSTANCES 1
/* Uncomment this if you need a filter for AOA devices:
* #define HAL_USBHAOA_FILTER_CALLBACK _try_aoa
*/
#define HAL_USBHAOA_DEFAULT_MANUFACTURER "Diego MFG & Co."
#define HAL_USBHAOA_DEFAULT_MODEL "Diego's device"
#define HAL_USBHAOA_DEFAULT_DESCRIPTION "Description of this device..."
#define HAL_USBHAOA_DEFAULT_VERSION "1.0"
#define HAL_USBHAOA_DEFAULT_URI NULL
#define HAL_USBHAOA_DEFAULT_SERIAL NULL
#define HAL_USBHAOA_DEFAULT_AUDIO_MODE USBHAOA_AUDIO_MODE_DISABLED
/* UVC */
#define HAL_USBH_USE_UVC 0
#define HAL_USBH_USE_UVC TRUE
#define HAL_USBHUVC_MAX_INSTANCES 1
#define HAL_USBHUVC_MAX_MAILBOX_SZ 70
#define HAL_USBHUVC_WORK_RAM_SIZE 20000
#define HAL_USBHUVC_STATUS_PACKETS_COUNT 10
/* HID */
#define HAL_USBH_USE_HID TRUE
#define HAL_USBHHID_MAX_INSTANCES 2
#define HAL_USBHHID_USE_INTERRUPT_OUT FALSE
/* HUB */
#define HAL_USBH_USE_HUB 1
#define HAL_USBH_USE_HUB TRUE
#define HAL_USBHHUB_MAX_INSTANCES 1
#define HAL_USBHHUB_MAX_PORTS 6
/* debug */
#define USBH_DEBUG_ENABLE 1
#define USBH_DEBUG_ENABLE TRUE
#define USBH_DEBUG_USBHD USBHD1
#define USBH_DEBUG_SD SD2
#define USBH_DEBUG_BUFFER 25000
#define USBH_DEBUG_ENABLE_TRACE 0
#define USBH_DEBUG_ENABLE_INFO 1
#define USBH_DEBUG_ENABLE_WARNINGS 1
#define USBH_DEBUG_ENABLE_ERRORS 1
#define USBH_DEBUG_ENABLE_TRACE FALSE
#define USBH_DEBUG_ENABLE_INFO TRUE
#define USBH_DEBUG_ENABLE_WARNINGS TRUE
#define USBH_DEBUG_ENABLE_ERRORS TRUE
#define USBH_LLD_DEBUG_ENABLE_TRACE 0
#define USBH_LLD_DEBUG_ENABLE_INFO 1
#define USBH_LLD_DEBUG_ENABLE_WARNINGS 1
#define USBH_LLD_DEBUG_ENABLE_ERRORS 1
#define USBH_LLD_DEBUG_ENABLE_TRACE FALSE
#define USBH_LLD_DEBUG_ENABLE_INFO TRUE
#define USBH_LLD_DEBUG_ENABLE_WARNINGS TRUE
#define USBH_LLD_DEBUG_ENABLE_ERRORS TRUE
#define USBHHUB_DEBUG_ENABLE_TRACE 0
#define USBHHUB_DEBUG_ENABLE_INFO 1
#define USBHHUB_DEBUG_ENABLE_WARNINGS 1
#define USBHHUB_DEBUG_ENABLE_ERRORS 1
#define USBHHUB_DEBUG_ENABLE_TRACE FALSE
#define USBHHUB_DEBUG_ENABLE_INFO TRUE
#define USBHHUB_DEBUG_ENABLE_WARNINGS TRUE
#define USBHHUB_DEBUG_ENABLE_ERRORS TRUE
#define USBHMSD_DEBUG_ENABLE_TRACE 0
#define USBHMSD_DEBUG_ENABLE_INFO 1
#define USBHMSD_DEBUG_ENABLE_WARNINGS 1
#define USBHMSD_DEBUG_ENABLE_ERRORS 1
#define USBHMSD_DEBUG_ENABLE_TRACE FALSE
#define USBHMSD_DEBUG_ENABLE_INFO TRUE
#define USBHMSD_DEBUG_ENABLE_WARNINGS TRUE
#define USBHMSD_DEBUG_ENABLE_ERRORS TRUE
#define USBHUVC_DEBUG_ENABLE_TRACE 0
#define USBHUVC_DEBUG_ENABLE_INFO 1
#define USBHUVC_DEBUG_ENABLE_WARNINGS 1
#define USBHUVC_DEBUG_ENABLE_ERRORS 1
#define USBHUVC_DEBUG_ENABLE_TRACE FALSE
#define USBHUVC_DEBUG_ENABLE_INFO TRUE
#define USBHUVC_DEBUG_ENABLE_WARNINGS TRUE
#define USBHUVC_DEBUG_ENABLE_ERRORS TRUE
#define USBHFTDI_DEBUG_ENABLE_TRACE 0
#define USBHFTDI_DEBUG_ENABLE_INFO 1
#define USBHFTDI_DEBUG_ENABLE_WARNINGS 1
#define USBHFTDI_DEBUG_ENABLE_ERRORS 1
#define USBHFTDI_DEBUG_ENABLE_TRACE FALSE
#define USBHFTDI_DEBUG_ENABLE_INFO TRUE
#define USBHFTDI_DEBUG_ENABLE_WARNINGS TRUE
#define USBHFTDI_DEBUG_ENABLE_ERRORS TRUE
#define USBHAOA_DEBUG_ENABLE_TRACE FALSE
#define USBHAOA_DEBUG_ENABLE_INFO TRUE
#define USBHAOA_DEBUG_ENABLE_WARNINGS TRUE
#define USBHAOA_DEBUG_ENABLE_ERRORS TRUE
#define USBHHID_DEBUG_ENABLE_TRACE FALSE
#define USBHHID_DEBUG_ENABLE_INFO TRUE
#define USBHHID_DEBUG_ENABLE_WARNINGS TRUE
#define USBHHID_DEBUG_ENABLE_ERRORS TRUE
/*===========================================================================*/
/* FSMCNAND driver related settings. */

View File

@ -1,33 +0,0 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
#else /* Embedded platform */
/* This type MUST be 8 bit */
typedef unsigned char BYTE;
/* These types MUST be 16 bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 16 bit or 32 bit */
typedef int INT;
typedef unsigned int UINT;
/* These types MUST be 32 bit */
typedef long LONG;
typedef unsigned long DWORD;
#endif
#endif

File diff suppressed because it is too large Load Diff