Add AOA (Android Accessory) class driver
This commit is contained in:
parent
a77ab485fb
commit
835bb887c0
|
@ -12,6 +12,7 @@ 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_uvc.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/src/hal_ee24xx.c \
|
||||
${CHIBIOS_CONTRIB}/os/hal/src/hal_ee25xx.c \
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
#define HAL_USBH_USE_UVC FALSE
|
||||
#endif
|
||||
|
||||
#ifndef HAL_USBH_USE_AOA
|
||||
#define HAL_USBH_USE_AOA FALSE
|
||||
#endif
|
||||
|
||||
#define HAL_USBH_USE_IAD HAL_USBH_USE_UVC
|
||||
|
||||
#if (HAL_USE_USBH == TRUE) || defined(__DOXYGEN__)
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
|
||||
Copyright (C) 2015 Diego Ismirlian, TISA, (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_ */
|
|
@ -29,6 +29,9 @@
|
|||
#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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
//devices
|
||||
#include "usbh/dev/hub.h"
|
||||
#include "usbh/dev/aoa.h"
|
||||
#include "usbh/dev/ftdi.h"
|
||||
#include "usbh/dev/msd.h"
|
||||
|
||||
|
@ -114,6 +115,9 @@ void usbhInit(void) {
|
|||
#if HAL_USBH_USE_FTDI
|
||||
usbhftdiInit();
|
||||
#endif
|
||||
#if HAL_USBH_USE_AOA
|
||||
usbhaoaInit();
|
||||
#endif
|
||||
#if HAL_USBH_USE_MSD
|
||||
usbhmsdInit();
|
||||
#endif
|
||||
|
@ -1303,7 +1307,10 @@ static const usbh_classdriverinfo_t *usbh_classdrivers_lookup[] = {
|
|||
&usbhmsdClassDriverInfo,
|
||||
#endif
|
||||
#if HAL_USBH_USE_HUB
|
||||
&usbhhubClassDriverInfo
|
||||
&usbhhubClassDriverInfo,
|
||||
#endif
|
||||
#if HAL_USBH_USE_AOA
|
||||
&usbhaoaClassDriverInfo, /* Leave always last */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
|
||||
Copyright (C) 2015..2016 Diego Ismirlian, TISA, (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_IN | USBH_REQTYPE_VENDOR | USBH_REQTYPE_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_OUT | USBH_REQTYPE_VENDOR | USBH_REQTYPE_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_OUT | USBH_REQTYPE_VENDOR | USBH_REQTYPE_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_OUT | USBH_REQTYPE_VENDOR | USBH_REQTYPE_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
|
|
@ -115,6 +115,20 @@
|
|||
#define HAL_USBHUVC_WORK_RAM_SIZE 20000
|
||||
#define HAL_USBHUVC_STATUS_PACKETS_COUNT 10
|
||||
|
||||
/* AOA */
|
||||
#define HAL_USBH_USE_AOA TRUE
|
||||
|
||||
#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
|
||||
|
||||
/* HUB */
|
||||
#define HAL_USBH_USE_HUB TRUE
|
||||
|
@ -159,6 +173,11 @@
|
|||
#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
|
||||
|
||||
/*===========================================================================*/
|
||||
/* FSMCNAND driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -19,18 +19,7 @@
|
|||
#include "ff.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
#if HAL_USBH_USE_FTDI
|
||||
#include "usbh/dev/ftdi.h"
|
||||
#include "shell.h"
|
||||
#include "chprintf.h"
|
||||
|
||||
static THD_WORKING_AREA(waTestFTDI, 1024);
|
||||
|
||||
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
|
||||
#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
|
||||
|
||||
#if HAL_USBH_USE_FTDI || HAL_USBH_USE_AOA
|
||||
static uint8_t buf[] =
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
|
@ -48,7 +37,17 @@ static uint8_t buf[] =
|
|||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
#endif
|
||||
|
||||
#if HAL_USBH_USE_FTDI
|
||||
#include "usbh/dev/ftdi.h"
|
||||
#include "shell.h"
|
||||
#include "chprintf.h"
|
||||
|
||||
static THD_WORKING_AREA(waTestFTDI, 1024);
|
||||
|
||||
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
|
||||
#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
|
||||
|
||||
static void cmd_write(BaseSequentialStream *chp, int argc, char *argv[]) {
|
||||
|
||||
|
@ -197,7 +196,92 @@ start:
|
|||
}
|
||||
#endif
|
||||
|
||||
#if HAL_USBH_USE_AOA
|
||||
#include "usbh/dev/aoa.h"
|
||||
#include "chprintf.h"
|
||||
|
||||
static THD_WORKING_AREA(waTestAOA, 1024);
|
||||
|
||||
#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
|
||||
#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
|
||||
|
||||
static void ThreadTestAOA(void *p) {
|
||||
(void)p;
|
||||
USBHAOADriver *const aoap = &USBHAOAD[0];
|
||||
USBHAOAChannel *const aoacp = &aoap->channel;
|
||||
|
||||
start:
|
||||
while (usbhaoaGetState(aoap) != USBHAOA_STATE_READY) {
|
||||
chThdSleepMilliseconds(100);
|
||||
}
|
||||
|
||||
usbDbgPuts("AOA: Connected");
|
||||
|
||||
if (usbhaoaGetChannelState(aoap) != USBHAOA_CHANNEL_STATE_READY) {
|
||||
usbhaoaChannelStart(aoap);
|
||||
usbDbgPuts("AOA: Channel started");
|
||||
}
|
||||
|
||||
//loopback
|
||||
if (1) {
|
||||
for(;;) {
|
||||
msg_t m = streamGet(aoacp);
|
||||
if (m < MSG_OK) {
|
||||
usbDbgPuts("AOA: Disconnected");
|
||||
goto start;
|
||||
}
|
||||
streamPut(aoacp, (uint8_t)m);
|
||||
if (m == 'q')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define AOA_WRITE_SPEED_TEST_BYTES 3000000UL
|
||||
//write speed test
|
||||
if (1) {
|
||||
systime_t st, et;
|
||||
int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
uint32_t bytes = AOA_WRITE_SPEED_TEST_BYTES;
|
||||
uint32_t times = bytes / 1024;
|
||||
st = chVTGetSystemTimeX();
|
||||
while (times--) {
|
||||
if (streamWrite(aoacp, buf, 1024) < 1024) {
|
||||
usbDbgPuts("AOA: Disconnected");
|
||||
goto start;
|
||||
}
|
||||
bytes -= 1024;
|
||||
}
|
||||
if (bytes) {
|
||||
if (streamWrite(aoacp, buf, bytes) < bytes) {
|
||||
usbDbgPuts("AOA: Disconnected");
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
et = chVTGetSystemTimeX();
|
||||
usbDbgPrintf("\tRate=%uB/s", AOA_WRITE_SPEED_TEST_BYTES / (et - st) * 100);
|
||||
}
|
||||
}
|
||||
|
||||
//single character write test (tests the timer)
|
||||
if (0) {
|
||||
for (;;) {
|
||||
if (streamPut(aoacp, 'A') != MSG_OK) {
|
||||
usbDbgPuts("AOA: Disconnected");
|
||||
goto start;
|
||||
}
|
||||
chThdSleepMilliseconds(100);
|
||||
}
|
||||
}
|
||||
|
||||
usbhaoaChannelStop(aoap);
|
||||
|
||||
usbDbgPuts("AOA: Tests done, restarting in 3s");
|
||||
chThdSleepMilliseconds(3000);
|
||||
|
||||
goto start;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAL_USBH_USE_MSD
|
||||
#include "usbh/dev/msd.h"
|
||||
|
@ -400,6 +484,10 @@ int main(void) {
|
|||
chThdCreateStatic(waTestFTDI, sizeof(waTestFTDI), NORMALPRIO, ThreadTestFTDI, 0);
|
||||
#endif
|
||||
|
||||
#if HAL_USBH_USE_AOA
|
||||
chThdCreateStatic(waTestAOA, sizeof(waTestAOA), NORMALPRIO, ThreadTestAOA, 0);
|
||||
#endif
|
||||
|
||||
//turn on USB power
|
||||
palClearPad(GPIOC, GPIOC_OTG_FS_POWER_ON);
|
||||
|
||||
|
|
Loading…
Reference in New Issue