623 lines
19 KiB
C
623 lines
19 KiB
C
|
/**
|
||
|
* @file usb_ctrl_transfer.c
|
||
|
* @brief usb 控制传输接口
|
||
|
* @author chenrixin@zh-jieli.com
|
||
|
* @version 1.00
|
||
|
* @date 2017-02-09
|
||
|
*/
|
||
|
|
||
|
#include "usb/host/usb_host.h"
|
||
|
#include "usb_ctrl_transfer.h"
|
||
|
#include "app_config.h"
|
||
|
#include "device_drive.h"
|
||
|
#include "gpio.h"
|
||
|
#include "usb/scsi.h"
|
||
|
|
||
|
#define LOG_TAG_CONST USB
|
||
|
#define LOG_TAG "[USB]"
|
||
|
#define LOG_ERROR_ENABLE
|
||
|
#define LOG_DEBUG_ENABLE
|
||
|
#define LOG_INFO_ENABLE
|
||
|
/* #define LOG_DUMP_ENABLE */
|
||
|
#define LOG_CLI_ENABLE
|
||
|
#include "debug.h"
|
||
|
|
||
|
#if USB_HOST_ENABLE
|
||
|
|
||
|
_WEAK_
|
||
|
void usb_dis_ep0_txdly(const usb_dev id)
|
||
|
{
|
||
|
}
|
||
|
static void ep0_h_isr(struct usb_host_device *host_dev, u32 ep)
|
||
|
{
|
||
|
usb_dev usb_id = host_device2id(host_dev);
|
||
|
usb_sem_post(host_dev);
|
||
|
}
|
||
|
/**
|
||
|
* @brief usb_ctlXfer
|
||
|
*
|
||
|
* @param host_dev
|
||
|
* @param urb
|
||
|
*
|
||
|
* @return
|
||
|
*/
|
||
|
static int usb_ctlXfer(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||
|
{
|
||
|
u32 ret = DEV_ERR_NONE;
|
||
|
u8 reg = 0;
|
||
|
u32 data_len;
|
||
|
usb_dev usb_id = host_device2id(host_dev);
|
||
|
u8 devnum = host_dev->private_data.devnum;
|
||
|
u32 max_packet_size = host_dev->private_data.ep0_max_packet_size;
|
||
|
|
||
|
usb_write_faddr(usb_id, devnum);
|
||
|
|
||
|
switch (urb->stage) {
|
||
|
case USB_PID_SETUP :
|
||
|
usb_write_ep0(usb_id, (u8 *)&urb->setup, 8);
|
||
|
reg = CSR0H_SetupPkt | CSR0H_TxPktRdy;
|
||
|
break;
|
||
|
case USB_PID_IN :
|
||
|
if (urb->setup.wLength) {
|
||
|
reg = CSR0H_ReqPkt;
|
||
|
} else {
|
||
|
reg = CSR0H_StatusPkt | CSR0H_ReqPkt;
|
||
|
}
|
||
|
break;
|
||
|
case USB_PID_OUT:
|
||
|
if (urb->setup.wLength) {
|
||
|
data_len = min(urb->setup.wLength, max_packet_size);
|
||
|
reg = CSR0H_TxPktRdy;
|
||
|
usb_write_ep0(usb_id, urb->buffer, data_len);
|
||
|
urb->setup.wLength -= data_len;
|
||
|
urb->buffer += data_len;
|
||
|
} else {
|
||
|
reg = CSR0H_StatusPkt | CSR0H_TxPktRdy;
|
||
|
}
|
||
|
break;
|
||
|
default :
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if USB_HOST_ASYNC
|
||
|
//config ep0 callback fun
|
||
|
usb_h_set_ep_isr(host_dev, 0, ep0_h_isr, host_dev);
|
||
|
usb_set_intr_txe(usb_id, 0);
|
||
|
#endif
|
||
|
|
||
|
usb_write_csr0(usb_id, reg);
|
||
|
|
||
|
u32 st = 0;
|
||
|
u32 ot = get_jiffies() + 500;
|
||
|
while (1) {
|
||
|
if (usb_host_timeout(ot)) {
|
||
|
log_error("time out %x\n", reg);
|
||
|
ret = -DEV_ERR_TIMEOUT;
|
||
|
goto __exit;
|
||
|
}
|
||
|
if (usb_h_dev_status(usb_id)) {
|
||
|
st ++;
|
||
|
} else {
|
||
|
st = 0;
|
||
|
}
|
||
|
if (((usb_read_devctl(usb_id) & BIT(2)) == 0) || (st > 1000)) {
|
||
|
log_error("usb%d_offline\n", usb_id);
|
||
|
ret = -DEV_ERR_OFFLINE;
|
||
|
goto __exit;
|
||
|
}
|
||
|
|
||
|
#if USB_HOST_ASYNC
|
||
|
ret = usb_sem_pend(host_dev, 250); //wait isr
|
||
|
if (ret) {
|
||
|
log_error("usb%d_offline\n", usb_id);
|
||
|
ret = -DEV_ERR_OFFLINE;
|
||
|
goto __exit;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
reg = usb_read_csr0(usb_id);
|
||
|
if (reg & CSR0H_RxStall) {
|
||
|
log_error(" rxStall CSR0:0x%x", reg);
|
||
|
ret = -DEV_ERR_CONTROL_STALL;
|
||
|
goto __exit;
|
||
|
}
|
||
|
if (reg & CSR0H_Error) {
|
||
|
log_error(" Error CSR0:0x%x", reg);
|
||
|
usb_write_csr0(usb_id, 0);
|
||
|
ret = -DEV_ERR_CONTROL;
|
||
|
goto __exit;
|
||
|
}
|
||
|
if (USB_PID_IN == urb->stage) {
|
||
|
|
||
|
if (reg & CSR0H_RxPktRdy) {
|
||
|
data_len = usb_read_count0(usb_id);
|
||
|
data_len = min(data_len, urb->setup.wLength);
|
||
|
usb_read_ep0(usb_id, urb->buffer, data_len);;
|
||
|
urb->buffer += data_len;
|
||
|
urb->setup.wLength -= data_len;
|
||
|
if (data_len < max_packet_size) {
|
||
|
urb->setup.wLength = 0;
|
||
|
}
|
||
|
if (urb->setup.wLength) {
|
||
|
usb_write_csr0(usb_id, CSR0H_ReqPkt);
|
||
|
} else {
|
||
|
usb_write_csr0(usb_id, 0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (!(reg & CSR0H_TxPktRdy)) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__exit:
|
||
|
usb_clr_intr_txe(usb_id, 0);
|
||
|
usb_dis_ep0_txdly(usb_id);
|
||
|
return ret;
|
||
|
}
|
||
|
/**
|
||
|
* @brief usb_control_transfers
|
||
|
*
|
||
|
* @param struct host_dev
|
||
|
* @param urb
|
||
|
*
|
||
|
* @return
|
||
|
*/
|
||
|
static int usb_control_transfers(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||
|
{
|
||
|
usb_dev usb_id = host_device2id(host_dev);
|
||
|
|
||
|
int res;
|
||
|
/*SETUP*/
|
||
|
|
||
|
urb->stage = USB_PID_SETUP; //SETUP transaction
|
||
|
|
||
|
res = usb_ctlXfer(host_dev, urb);
|
||
|
|
||
|
if (res) {
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
/*IN or OUT*/
|
||
|
urb->stage = USB_PID_IN;
|
||
|
|
||
|
|
||
|
while (urb->setup.wLength) {
|
||
|
if (urb->setup.bRequestType & USB_DIR_IN) { //Request Direction
|
||
|
urb->stage = USB_PID_IN; //IN transaction
|
||
|
|
||
|
res = usb_ctlXfer(host_dev, urb);
|
||
|
|
||
|
if (res) {
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
urb->stage = USB_PID_OUT;
|
||
|
} else {
|
||
|
urb->stage = USB_PID_OUT; //OUT transaction
|
||
|
|
||
|
res = usb_ctlXfer(host_dev, urb);
|
||
|
|
||
|
if (res) {
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
urb->stage = USB_PID_IN;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
res = usb_ctlXfer(host_dev, urb);
|
||
|
|
||
|
if (res) {
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
return DEV_ERR_NONE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief usb_control_msg
|
||
|
*
|
||
|
* @param host_dev
|
||
|
* @param request
|
||
|
* @param requesttype
|
||
|
* @param value
|
||
|
* @param index
|
||
|
* @param data
|
||
|
* @param size
|
||
|
*
|
||
|
* @return
|
||
|
*/
|
||
|
static int usb_control_msg(struct usb_host_device *host_dev,
|
||
|
u8 request, u8 requesttype,
|
||
|
u16 value, u16 index,
|
||
|
void *data, u16 size)
|
||
|
{
|
||
|
struct ctlXfer urb;
|
||
|
urb.setup.bRequestType = requesttype;
|
||
|
urb.setup.bRequest = request;
|
||
|
urb.setup.wValue = cpu_to_le16(value);
|
||
|
urb.setup.wIndex = cpu_to_le16(index);
|
||
|
urb.setup.wLength = cpu_to_le16(size);
|
||
|
urb.buffer = data;
|
||
|
|
||
|
return usb_control_transfers(host_dev, &urb);
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief usb_clear_feature
|
||
|
*
|
||
|
* @param host_dev
|
||
|
* @param ep
|
||
|
*
|
||
|
* @return
|
||
|
*/
|
||
|
int usb_clear_feature(struct usb_host_device *host_dev, u32 ep)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, ep, NULL, 0);
|
||
|
}
|
||
|
|
||
|
int set_address(struct usb_host_device *host_dev, u8 devnum)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0);
|
||
|
}
|
||
|
|
||
|
int usb_get_device_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_DEVICE << 8),
|
||
|
0,
|
||
|
desc,
|
||
|
USB_DT_DEVICE_SIZE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
int usb_get_string_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||
|
{
|
||
|
int ret = DEV_ERR_NONE;
|
||
|
#if 0
|
||
|
struct usb_private_data *private_data = host_dev->private_data ;
|
||
|
/**********get string language*********/
|
||
|
u8 buf[16];
|
||
|
memset(buf, 0x0, sizeof(buf));
|
||
|
ret = usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_STRING << 8),
|
||
|
0,
|
||
|
desc,
|
||
|
sizeof(buf)
|
||
|
);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
memcpy(&private_data->language, buf + 2, sizeof(private_data->language));
|
||
|
|
||
|
/**********get manufacturer string**********/
|
||
|
memset(private_data->manufacturer, 0x0, sizeof(private_data->manufacturer));
|
||
|
if (desc->iManufacturer) {
|
||
|
ret = usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_STRING << 8) | desc->iManufacturer,
|
||
|
0,
|
||
|
private_data->manufacturer,
|
||
|
sizeof(private_data->manufacturer)
|
||
|
);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
/**********get product string**********/
|
||
|
memset(private_data->product, 0x0, sizeof(private_data->product));
|
||
|
if (desc->iProduct) {
|
||
|
ret = usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_STRING << 8) | desc->iProduct,
|
||
|
0,
|
||
|
private_data->product,
|
||
|
sizeof(private_data->product)
|
||
|
);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int set_configuration(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0);
|
||
|
}
|
||
|
int set_configuration_add_value(struct usb_host_device *host_dev, u16 value)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, value, 0, NULL, 0);
|
||
|
}
|
||
|
int get_config_descriptor(struct usb_host_device *host_dev, void *cfg_desc, u32 len)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_CONFIG << 8),
|
||
|
0,
|
||
|
cfg_desc,
|
||
|
len);
|
||
|
}
|
||
|
|
||
|
int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_CONFIG << 8) | value_l,
|
||
|
0,
|
||
|
cfg_desc,
|
||
|
len);
|
||
|
}
|
||
|
|
||
|
|
||
|
int get_msd_max_lun(struct usb_host_device *host_dev, void *lun)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_MSD_MAX_LUN,
|
||
|
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||
|
0,
|
||
|
0,
|
||
|
lun,
|
||
|
1);
|
||
|
}
|
||
|
int set_msd_reset(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
0xff,
|
||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||
|
0,
|
||
|
0,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
|
||
|
int hid_set_idle(struct usb_host_device *host_dev, u32 id)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, 0x0a, 0x21, 0, id << 8, NULL, 0);
|
||
|
}
|
||
|
int hid_get_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u16 report_len)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN | USB_RECIP_INTERFACE,
|
||
|
0x2200,
|
||
|
report_id,
|
||
|
report,
|
||
|
report_len);
|
||
|
}
|
||
|
int hid_set_output_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u8 report_len)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
0x09,
|
||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||
|
0x0201,
|
||
|
report_id,
|
||
|
report,
|
||
|
report_len);
|
||
|
}
|
||
|
int usb_set_remote_wakeup(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
return usb_control_msg(host_dev, USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
|
||
|
USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0);
|
||
|
}
|
||
|
int get_device_status(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
u16 status;
|
||
|
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN, 0, 0, (u8 *)&status, 2);
|
||
|
}
|
||
|
int usb_get_device_qualifier(struct usb_host_device *host_dev, u8 *buffer)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_GET_DESCRIPTOR,
|
||
|
USB_DIR_IN,
|
||
|
(USB_DT_DEVICE_QUALIFIER << 8),
|
||
|
0,
|
||
|
buffer,
|
||
|
0x0a);
|
||
|
|
||
|
}
|
||
|
#define AOA_CMD51 0x33
|
||
|
#define AOA_CMD52 0x34
|
||
|
#define AOA_CMD53 0x35
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
AOA_CMD51,
|
||
|
USB_DIR_IN | USB_TYPE_VENDOR,
|
||
|
0,
|
||
|
0,
|
||
|
version,
|
||
|
2);
|
||
|
}
|
||
|
int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
AOA_CMD52,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
0,
|
||
|
index,
|
||
|
(u8 *)string,
|
||
|
strlen(string));
|
||
|
}
|
||
|
int usb_switch2aoa(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
AOA_CMD53,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
0,
|
||
|
0,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
int usb_switch2slave(struct usb_host_device *host_dev)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
0x51,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
0,
|
||
|
0,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
/* Control request for registering a HID device.
|
||
|
* Upon registering, a unique ID is sent by the accessory in the
|
||
|
* value parameter. This ID will be used for future commands for
|
||
|
* the device
|
||
|
*
|
||
|
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||
|
* request: ACCESSORY_REGISTER_HID_DEVICE
|
||
|
* value: Accessory assigned ID for the HID device
|
||
|
* index: total length of the HID report descriptor
|
||
|
* data none
|
||
|
*/
|
||
|
#define ACCESSORY_REGISTER_HID 54
|
||
|
int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
ACCESSORY_REGISTER_HID,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
value,
|
||
|
index,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
/* Control request for unregistering a HID device.
|
||
|
*
|
||
|
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||
|
* request: ACCESSORY_REGISTER_HID
|
||
|
* value: Accessory assigned ID for the HID device
|
||
|
* index: 0
|
||
|
* data none
|
||
|
*/
|
||
|
#define ACCESSORY_UNREGISTER_HID 55
|
||
|
int usb_aoa_unregister_hid(struct usb_host_device *host_dev, u16 value)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
ACCESSORY_UNREGISTER_HID,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
value,
|
||
|
0,
|
||
|
NULL,
|
||
|
0);
|
||
|
}
|
||
|
|
||
|
/* Control request for sending the HID report descriptor.
|
||
|
* If the HID descriptor is longer than the endpoint zero max packet size,
|
||
|
* the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
|
||
|
* commands. The data for the descriptor must be sent sequentially
|
||
|
* if multiple packets are needed.
|
||
|
*
|
||
|
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||
|
* request: ACCESSORY_SET_HID_REPORT_DESC
|
||
|
* value: Accessory assigned ID for the HID device
|
||
|
* index: offset of data in descriptor
|
||
|
* (needed when HID descriptor is too big for one packet)
|
||
|
* data the HID report descriptor
|
||
|
*/
|
||
|
#define ACCESSORY_SET_HID_REPORT_DESC 56
|
||
|
int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
ACCESSORY_SET_HID_REPORT_DESC,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
value,
|
||
|
offset,
|
||
|
(u8 *)pbuf,
|
||
|
len);
|
||
|
}
|
||
|
|
||
|
/* Control request for sending HID events.
|
||
|
*
|
||
|
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||
|
* request: ACCESSORY_SEND_HID_EVENT
|
||
|
* value: Accessory assigned ID for the HID device
|
||
|
* index: 0
|
||
|
* data the HID report for the event
|
||
|
*/
|
||
|
#define ACCESSORY_SEND_HID_EVENT 57
|
||
|
int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
ACCESSORY_SEND_HID_EVENT,
|
||
|
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||
|
value,
|
||
|
0,
|
||
|
(u8 *)pbuf,
|
||
|
len);
|
||
|
}
|
||
|
int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer)
|
||
|
{
|
||
|
return usb_control_msg(host_dev,
|
||
|
0x01,
|
||
|
USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
||
|
0x0000,
|
||
|
4,
|
||
|
buffer,
|
||
|
0x28);
|
||
|
}
|
||
|
|
||
|
|
||
|
int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting)
|
||
|
{
|
||
|
log_info("%s Set Interface:%d AlternateSetting:%d", __func__, interface, alternateSetting);
|
||
|
return usb_control_msg(host_dev,
|
||
|
USB_REQ_SET_INTERFACE,
|
||
|
USB_RECIP_INTERFACE,
|
||
|
alternateSetting,
|
||
|
interface,
|
||
|
NULL,
|
||
|
0);
|
||
|
|
||
|
}
|
||
|
|
||
|
int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate)
|
||
|
{
|
||
|
log_info("%s ep:%d sampe_rate:%d", __func__, ep, sampe_rate);
|
||
|
return usb_control_msg(host_dev,
|
||
|
1,
|
||
|
USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
|
||
|
0x0100,
|
||
|
ep,
|
||
|
&sampe_rate,
|
||
|
3);
|
||
|
}
|
||
|
int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume)
|
||
|
{
|
||
|
log_info("%s featureID:%d vol:%x", __func__, feature_id, volume);
|
||
|
return usb_control_msg(host_dev,
|
||
|
1,
|
||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||
|
(0x02 << 8) | channel_num,
|
||
|
feature_id << 8,
|
||
|
&volume,
|
||
|
2);
|
||
|
}
|
||
|
int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute)
|
||
|
{
|
||
|
log_info("%s featureID:%d mute:%d", __func__, feature_id, mute);
|
||
|
return usb_control_msg(host_dev,
|
||
|
1,
|
||
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||
|
0x0100,
|
||
|
feature_id << 8,
|
||
|
&mute,
|
||
|
1);
|
||
|
}
|
||
|
#endif
|