mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-07-10 13:29:52 -04:00
this commit is a combination of the following changes, which significantly refactors usb core and class drivers. 1. unify usb buffers of each class driver to reduce iram usage currently, many class drivers allocate their own buffer to receive control out data, which is a waste of iram. share one common buffer for that usage to address the issue. 2. simplify control request handling by implicitly receiving write request data packets change 1 above fixed the data destination. therefore, having the core receive the data allows us to reduce the class driver's work and simplifies the api. 3. enhance usb core's control request handling and unify the legacy driver api in order to implement change 2, both the legacy and new driver apis should be supported. so that, using the designware driver as a reference, the new driver api functionality is move into usb core. this simplifies the usb device drivers by requiring them to implement only the functionalities equivalent to the legacy api. tested with ipodvideo(arc) and erosqnative(designware) Change-Id: I3627daa90278751f599e2108ec150ec3f8f6c524
145 lines
5.6 KiB
C
145 lines
5.6 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2008 Frank Gevaerts
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef _USB_CLASS_DRIVER_H_
|
|
#define _USB_CLASS_DRIVER_H_
|
|
|
|
#include "usb_ch9.h"
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
/* Common api, implemented by all class drivers */
|
|
|
|
struct usb_class_driver_ep_allocation {
|
|
uint8_t ep; /* by core, allocated ep. > 0 are valid but can be 0 if optional==true */
|
|
uint8_t type:2; /* by driver, required ep type. USB_ENDPOINT_XFER_* */
|
|
uint8_t dir:1; /* by driver, required ep dir. DIR_{IN,OUT} */
|
|
bool optional:1; /* by driver, set true to mark this requirement to be optional */
|
|
int16_t mps; /* by driver, desired max packet size, or -1 for device driver default */
|
|
};
|
|
|
|
struct usb_class_driver {
|
|
/* First some runtime data */
|
|
|
|
/* there are three possible runtime states for class driver:
|
|
* !enabled -> disabled, invisible from host
|
|
* enabled && !error -> enabled, healthy
|
|
* enabled && error -> recognized by host, but failed */
|
|
bool enabled;
|
|
bool error;
|
|
|
|
int first_interface;
|
|
int last_interface;
|
|
|
|
/* Driver api starts here */
|
|
|
|
/* Set this to true if the driver needs exclusive disk access (e.g. usb storage) */
|
|
bool needs_exclusive_storage;
|
|
|
|
/* Set this to true if the driver needs to enable cpu boost */
|
|
bool needs_cpu_boost;
|
|
|
|
/* USB config number this driver belongs to */
|
|
uint8_t config;
|
|
|
|
/* Endpoint allocation state table */
|
|
uint8_t ep_allocs_size;
|
|
struct usb_class_driver_ep_allocation* ep_allocs;
|
|
|
|
/* Tells the driver what its first interface number will be. The driver
|
|
returns the number of the first available interface for the next driver
|
|
(i.e. a driver with one interface will return interface+1)
|
|
A driver must have at least one interface
|
|
Mandatory function */
|
|
int (*set_first_interface)(int interface);
|
|
|
|
/* Asks the driver to put the interface descriptor and all other
|
|
needed descriptor for this driver at dest.
|
|
Returns the number of bytes taken by these descriptors.
|
|
Mandatory function */
|
|
int (*get_config_descriptor)(unsigned char *dest, int max_packet_size);
|
|
|
|
/* Tells the driver that a usb connection has been set up and is now
|
|
ready to use.
|
|
Returns 0 on success and -1 on error.
|
|
Optional function */
|
|
int (*init_connection)(void);
|
|
|
|
/* Initialises the driver. This can be called multiple times,
|
|
and should not perform any action that can disturb other threads
|
|
(like getting the audio buffer)
|
|
Optional function */
|
|
void (*init)(void);
|
|
|
|
/* Tells the driver that the usb connection is no longer active
|
|
Optional function */
|
|
void (*disconnect)(void);
|
|
|
|
/* Tells the driver that a usb transfer has been completed. Note that "dir"
|
|
is relative to the host
|
|
Optional function */
|
|
void (*transfer_complete)(int ep, int dir, int status, int length);
|
|
|
|
/* Similar to transfer_complete but called directly instead of going through
|
|
* the usb queue. Since it might be called in an interrupt context,
|
|
* processing should be kept to a minimum. This is mainly intended for
|
|
* isochronous transfers.
|
|
* The function must return true if it handled the completion, and false
|
|
* otherwise so that it is dispatched to the normal handler
|
|
* Optional function */
|
|
bool (*fast_transfer_complete)(int ep, int dir, int status, int length);
|
|
|
|
/* Tells the driver that a control request has come in. If the driver is
|
|
able to handle it, it should ack the request, and return true. Otherwise
|
|
it should return false.
|
|
Optional function */
|
|
bool (*control_request)(struct usb_ctrlrequest* req, uint8_t* reqdata, size_t reqdata_size);
|
|
|
|
#ifdef HAVE_HOTSWAP
|
|
/* Tells the driver that a hotswappable disk/card was inserted or
|
|
extracted
|
|
Optional function */
|
|
void (*notify_hotswap)(int volume, bool inserted);
|
|
#endif
|
|
|
|
/* Tells the driver to select an alternate setting for a specific interface.
|
|
* Returns 0 on success and -1 on error.
|
|
* Mandatory function if alternate interface support is needed */
|
|
int (*set_interface)(int interface, int alt_setting);
|
|
|
|
/* Asks the driver what is the current alternate setting for a specific interface.
|
|
* Returns value on success and -1 on error.
|
|
* Mandatory function if alternate interface support is needed */
|
|
int (*get_interface)(int interface);
|
|
|
|
/* Invoked by USB_NOTIFY_CLASS_DRIVER
|
|
Optional function */
|
|
void (*notify_event)(intptr_t data);
|
|
};
|
|
|
|
#define PACK_DATA(dest, data) pack_data(dest, &(data), sizeof(data))
|
|
static inline void pack_data(uint8_t **dest, const void *data, size_t size)
|
|
{
|
|
memcpy(*dest, data, size);
|
|
*dest += size;
|
|
}
|
|
#endif
|