初版
This commit is contained in:
@@ -0,0 +1,637 @@
|
||||
/**
|
||||
* @file usb_ctrl_transfer.c
|
||||
* @brief usb 控制传输接口
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.00
|
||||
* @date 2017-02-09
|
||||
*/
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".usb.data.bss")
|
||||
#pragma data_seg(".usb.data")
|
||||
#pragma code_seg(".usb.text")
|
||||
#pragma const_seg(".usb.text.const")
|
||||
#pragma str_literal_override(".usb.text.const")
|
||||
#endif
|
||||
|
||||
#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 TCFG_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_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);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_txfuncaddr(usb_id, 0, devnum);
|
||||
#endif
|
||||
|
||||
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 = (u8 *)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 | CSR0H_DISPING);
|
||||
|
||||
u32 st = 0;
|
||||
u32 ot = usb_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 = (u8 *)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 | CSR0H_DISPING);
|
||||
} else {
|
||||
usb_write_csr0(usb_id, CSR0H_DISPING);
|
||||
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)
|
||||
{
|
||||
|
||||
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
|
||||
*/
|
||||
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, u8 *status)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, status, 2);
|
||||
}
|
||||
int get_interface_status(struct usb_host_device *host_dev, u8 intr, u8 *status)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_INTERFACE, 0, intr, status, 2);
|
||||
}
|
||||
int get_endpoint_status(struct usb_host_device *host_dev, u8 ep, u8 *status)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, ep, 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
|
||||
Reference in New Issue
Block a user