diff --git a/drivers/usb/gadget/function/ci13xxx_udc.h b/drivers/usb/gadget/function/ci13xxx_udc.h new file mode 100644 index 0000000..7983bfd --- /dev/null +++ b/drivers/usb/gadget/function/ci13xxx_udc.h @@ -0,0 +1,280 @@ +/* + * ci13xxx_udc.h - structures, registers, and macros MIPS USB IP core + * + * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. + * + * Author: David Lopo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Description: MIPS USB IP core family device controller + * Structures, registers and logging macros + */ + +#ifndef _CI13XXX_h_ +#define _CI13XXX_h_ + +/****************************************************************************** + * DEFINE + *****************************************************************************/ +#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ +#define ENDPT_MAX (32) +#define CTRL_PAYLOAD_MAX (64) +#define RX (0) /* similar to USB_DIR_OUT but can be used as an index */ +#define TX (1) /* similar to USB_DIR_IN but can be used as an index */ + +/* UDC private data: + * 16MSb - Vendor ID | 16 LSb Vendor private data + */ +#define CI13XX_REQ_VENDOR_ID(id) (id & 0xFFFF0000UL) + +#define MSM_ETD_TYPE BIT(1) +#define MSM_EP_PIPE_ID_RESET_VAL 0x1F001F + +/****************************************************************************** + * STRUCTURES + *****************************************************************************/ +/* DMA layout of transfer descriptors */ +struct ci13xxx_td { + /* 0 */ + u32 next; +#define TD_TERMINATE BIT(0) +#define TD_ADDR_MASK (0xFFFFFFEUL << 5) + /* 1 */ + u32 token; +#define TD_STATUS (0x00FFUL << 0) +#define TD_STATUS_TR_ERR BIT(3) +#define TD_STATUS_DT_ERR BIT(5) +#define TD_STATUS_HALTED BIT(6) +#define TD_STATUS_ACTIVE BIT(7) +#define TD_MULTO (0x0003UL << 10) +#define TD_IOC BIT(15) +#define TD_TOTAL_BYTES (0x7FFFUL << 16) + /* 2 */ + u32 page[5]; +#define TD_CURR_OFFSET (0x0FFFUL << 0) +#define TD_FRAME_NUM (0x07FFUL << 0) +#define TD_RESERVED_MASK (0x0FFFUL << 0) +} __attribute__ ((packed, aligned(4))); + +/* DMA layout of queue heads */ +struct ci13xxx_qh { + /* 0 */ + u32 cap; +#define QH_IOS BIT(15) +#define QH_MAX_PKT (0x07FFUL << 16) +#define QH_ZLT BIT(29) +#define QH_MULT (0x0003UL << 30) +#define QH_MULT_SHIFT 11 + /* 1 */ + u32 curr; + /* 2 - 8 */ + struct ci13xxx_td td; + /* 9 */ + u32 RESERVED; + struct usb_ctrlrequest setup; +} __attribute__ ((packed, aligned(4))); + +/* cache of larger request's original attributes */ +struct ci13xxx_multi_req { + unsigned len; + unsigned actual; + void *buf; +}; + +/* Extension of usb_request */ +struct ci13xxx_req { + struct usb_request req; + unsigned map; + struct list_head queue; + struct ci13xxx_td *ptr; + dma_addr_t dma; + struct ci13xxx_td *zptr; + dma_addr_t zdma; + struct ci13xxx_multi_req multi; +}; + +/* Extension of usb_ep */ +struct ci13xxx_ep { + struct usb_ep ep; + const struct usb_endpoint_descriptor *desc; + u8 dir; + u8 num; + u8 type; + char name[16]; + struct { + struct list_head queue; + struct ci13xxx_qh *ptr; + dma_addr_t dma; + } qh; + struct list_head rw_queue; + int wedge; + + /* global resources */ + spinlock_t *lock; + struct device *device; + struct dma_pool *td_pool; + struct ci13xxx_td *last_zptr; + dma_addr_t last_zdma; + unsigned long dTD_update_fail_count; + unsigned long dTD_active_re_q_count; + unsigned long prime_fail_count; + int prime_timer_count; + struct timer_list prime_timer; + + bool multi_req; +}; + +struct ci13xxx; +struct ci13xxx_udc_driver { + const char *name; + unsigned long flags; + unsigned int nz_itc; +#define CI13XXX_REGS_SHARED BIT(0) +#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) +#define CI13XXX_PULLUP_ON_VBUS BIT(2) +#define CI13XXX_DISABLE_STREAMING BIT(3) +#define CI13XXX_ZERO_ITC BIT(4) +#define CI13XXX_ENABLE_AHB2AHB_BYPASS BIT(6) + +#define CI13XXX_CONTROLLER_RESET_EVENT 0 +#define CI13XXX_CONTROLLER_CONNECT_EVENT 1 +#define CI13XXX_CONTROLLER_SUSPEND_EVENT 2 +#define CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT 3 +#define CI13XXX_CONTROLLER_RESUME_EVENT 4 +#define CI13XXX_CONTROLLER_DISCONNECT_EVENT 5 +#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT 6 +#define CI13XXX_CONTROLLER_ERROR_EVENT 7 + + void (*notify_event)(struct ci13xxx *udc, unsigned event); + bool (*in_lpm)(struct ci13xxx *udc); +}; + +/* CI13XXX UDC descriptor & global resources */ +struct ci13xxx { + spinlock_t *lock; /* ctrl register bank access */ + void __iomem *regs; /* registers address space */ + + struct dma_pool *qh_pool; /* DMA pool for queue heads */ + struct dma_pool *td_pool; /* DMA pool for transfer descs */ + struct usb_request *status; /* ep0 status request */ + void *status_buf;/* GET_STATUS buffer */ + + struct usb_gadget gadget; /* USB slave device */ + struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ + u32 ep0_dir; /* ep0 direction */ +#define ep0out ci13xxx_ep[0] +#define ep0in ci13xxx_ep[hw_ep_max / 2] + u8 suspended; /* suspended by the host */ + u8 configured; /* is device configured */ + u8 test_mode; /* the selected test mode */ + bool rw_pending; /* Remote wakeup pending flag */ + struct delayed_work rw_work; /* remote wakeup delayed work */ + struct usb_gadget_driver *driver; /* 3rd party gadget driver */ + struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ + int vbus_active; /* is VBUS active */ + int softconnect; /* is pull-up enable allowed */ + unsigned long dTD_update_fail_count; + struct usb_phy *transceiver; /* Transceiver struct */ + bool skip_flush; /* skip flushing remaining EP + upon flush timeout for the + first EP. */ +}; + +/****************************************************************************** + * REGISTERS + *****************************************************************************/ +/* register size */ +#define REG_BITS (32) + +/* HCCPARAMS */ +#define HCCPARAMS_LEN BIT(17) + +/* DCCPARAMS */ +#define DCCPARAMS_DEN (0x1F << 0) +#define DCCPARAMS_DC BIT(7) + +/* TESTMODE */ +#define TESTMODE_FORCE BIT(0) + +/* AHB_MODE */ +#define AHB2AHB_BYPASS BIT(31) + +/* USBCMD */ +#define USBCMD_RS BIT(0) +#define USBCMD_RST BIT(1) +#define USBCMD_SUTW BIT(13) +#define USBCMD_ATDTW BIT(14) + +/* USBSTS & USBINTR */ +#define USBi_UI BIT(0) +#define USBi_UEI BIT(1) +#define USBi_PCI BIT(2) +#define USBi_URI BIT(6) +#define USBi_SLI BIT(8) + +/* DEVICEADDR */ +#define DEVICEADDR_USBADRA BIT(24) +#define DEVICEADDR_USBADR (0x7FUL << 25) + +/* PORTSC */ +#define PORTSC_FPR BIT(6) +#define PORTSC_SUSP BIT(7) +#define PORTSC_PR BIT(8) +#define PORTSC_HSP BIT(9) +#define PORTSC_PTC (0x0FUL << 16) + +/* DEVLC */ +#define DEVLC_PSPD (0x03UL << 25) +#define DEVLC_PSPD_HS (0x02UL << 25) + +/* USBMODE */ +#define USBMODE_CM (0x03UL << 0) +#define USBMODE_CM_IDLE (0x00UL << 0) +#define USBMODE_CM_DEVICE (0x02UL << 0) +#define USBMODE_CM_HOST (0x03UL << 0) +#define USBMODE_SLOM BIT(3) +#define USBMODE_SDIS BIT(4) +#define USBCMD_ITC(n) (n << 16) /* n = 0, 1, 2, 4, 8, 16, 32, 64 */ +#define USBCMD_ITC_MASK (0xFF << 16) + +/* ENDPTCTRL */ +#define ENDPTCTRL_RXS BIT(0) +#define ENDPTCTRL_RXT (0x03UL << 2) +#define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */ +#define ENDPTCTRL_RXE BIT(7) +#define ENDPTCTRL_TXS BIT(16) +#define ENDPTCTRL_TXT (0x03UL << 18) +#define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */ +#define ENDPTCTRL_TXE BIT(23) + +/****************************************************************************** + * LOGGING + *****************************************************************************/ +#define ci13xxx_printk(level, format, args...) \ +do { \ + if (_udc == NULL) \ + printk(level "[%s] " format "\n", __func__, ## args); \ + else \ + dev_printk(level, _udc->gadget.dev.parent, \ + "[%s] " format "\n", __func__, ## args); \ +} while (0) + +#ifndef err +#define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args) +#endif + +#define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args) +#define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args) + +#ifdef TRACE +#define trace(format, args...) ci13xxx_printk(KERN_DEBUG, format, ## args) +#define dbg_trace(format, args...) dev_dbg(dev, format, ##args) +#else +#define trace(format, args...) do {} while (0) +#define dbg_trace(format, args...) do {} while (0) +#endif + +#endif /* _CI13XXX_h_ */ diff --git a/drivers/usb/gadget/function/configfs.h b/drivers/usb/gadget/function/configfs.h new file mode 100644 index 0000000..36c468c --- /dev/null +++ b/drivers/usb/gadget/function/configfs.h @@ -0,0 +1,19 @@ +#ifndef USB__GADGET__CONFIGFS__H +#define USB__GADGET__CONFIGFS__H + +#include + +void unregister_gadget_item(struct config_item *item); + +int usb_os_desc_prepare_interf_dir(struct config_group *parent, + int n_interf, + struct usb_os_desc **desc, + char **names, + struct module *owner); + +static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item) +{ + return container_of(to_config_group(item), struct usb_os_desc, group); +} + +#endif /* USB__GADGET__CONFIGFS__H */ diff --git a/drivers/usb/gadget/function/debug.h b/drivers/usb/gadget/function/debug.h new file mode 100644 index 0000000..8729aca --- /dev/null +++ b/drivers/usb/gadget/function/debug.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DEBUG_H_ +#define __DEBUG_H_ + +#define DBG_MAX_MSG 1024UL +#define DBG_MSG_LEN 80UL +#define TIME_BUF_LEN 17 +#define DBG_EVENT_LEN (DBG_MSG_LEN - TIME_BUF_LEN) + +extern unsigned int enable_event_log; +extern void put_timestamp(char *tbuf); +extern void add_event_to_buf(char *tbuf); +extern int debug_debugfs_init(void); +extern void debug_debugfs_exit(void); + +#define LOGLEVEL_NONE 8 +#define LOGLEVEL_DEBUG 7 +#define LOGLEVEL_INFO 6 +#define LOGLEVEL_ERR 3 + +#define log_event(log_level, x...) \ +do { \ + char buf[DBG_MSG_LEN]; \ + if (log_level == LOGLEVEL_DEBUG) \ + pr_debug(x); \ + else if (log_level == LOGLEVEL_ERR) \ + pr_err(x); \ + else if (log_level == LOGLEVEL_INFO) \ + pr_info(x); \ + if (enable_event_log) { \ + put_timestamp(buf); \ + snprintf(&buf[TIME_BUF_LEN - 1], DBG_EVENT_LEN, x); \ + add_event_to_buf(buf); \ + } \ +} while (0) + +#define log_event_none(x, ...) log_event(LOGLEVEL_NONE, x, ##__VA_ARGS__) +#define log_event_dbg(x, ...) log_event(LOGLEVEL_DEBUG, x, ##__VA_ARGS__) +#define log_event_err(x, ...) log_event(LOGLEVEL_ERR, x, ##__VA_ARGS__) +#define log_event_info(x, ...) log_event(LOGLEVEL_INFO, x, ##__VA_ARGS__) + +#endif /* __DEBUG_H_ */ diff --git a/drivers/usb/gadget/function/f_ccid.h b/drivers/usb/gadget/function/f_ccid.h new file mode 100644 index 0000000..d899044 --- /dev/null +++ b/drivers/usb/gadget/function/f_ccid.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, The Linux Foundation. All rights reserved. + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + */ + +#ifndef __F_CCID_H +#define __F_CCID_H + +#define PROTOCOL_TO 0x01 +#define PROTOCOL_T1 0x02 +#define ABDATA_SIZE 512 + +/* define for dwFeatures for Smart Card Device Class Descriptors */ +/* No special characteristics */ +#define CCID_FEATURES_NADA 0x00000000 +/* Automatic parameter configuration based on ATR data */ +#define CCID_FEATURES_AUTO_PCONF 0x00000002 +/* Automatic activation of ICC on inserting */ +#define CCID_FEATURES_AUTO_ACTIV 0x00000004 +/* Automatic ICC voltage selection */ +#define CCID_FEATURES_AUTO_VOLT 0x00000008 +/* Automatic ICC clock frequency change */ +#define CCID_FEATURES_AUTO_CLOCK 0x00000010 +/* Automatic baud rate change */ +#define CCID_FEATURES_AUTO_BAUD 0x00000020 +/*Automatic parameters negotiation made by the CCID */ +#define CCID_FEATURES_AUTO_PNEGO 0x00000040 +/* Automatic PPS made by the CCID according to the active parameters */ +#define CCID_FEATURES_AUTO_PPS 0x00000080 +/* CCID can set ICC in clock stop mode */ +#define CCID_FEATURES_ICCSTOP 0x00000100 +/* NAD value other than 00 accepted (T=1 protocol in use) */ +#define CCID_FEATURES_NAD 0x00000200 +/* Automatic IFSD exchange as first exchange (T=1 protocol in use) */ +#define CCID_FEATURES_AUTO_IFSD 0x00000400 +/* TPDU level exchanges with CCID */ +#define CCID_FEATURES_EXC_TPDU 0x00010000 +/* Short APDU level exchange with CCID */ +#define CCID_FEATURES_EXC_SAPDU 0x00020000 +/* Short and Extended APDU level exchange with CCID */ +#define CCID_FEATURES_EXC_APDU 0x00040000 +/* USB Wake up signaling supported on card insertion and removal */ +#define CCID_FEATURES_WAKEUP 0x00100000 + +#define CCID_NOTIFY_CARD _IOW('C', 1, struct usb_ccid_notification) +#define CCID_NOTIFY_HWERROR _IOW('C', 2, struct usb_ccid_notification) +#define CCID_READ_DTR _IOR('C', 3, int) + +struct usb_ccid_notification { + unsigned char buf[4]; +} __packed; + +struct ccid_bulk_in_header { + unsigned char bMessageType; + unsigned long wLength; + unsigned char bSlot; + unsigned char bSeq; + unsigned char bStatus; + unsigned char bError; + unsigned char bSpecific; + unsigned char abData[ABDATA_SIZE]; + unsigned char bSizeToSend; +} __packed; + +struct ccid_bulk_out_header { + unsigned char bMessageType; + unsigned long wLength; + unsigned char bSlot; + unsigned char bSeq; + unsigned char bSpecific_0; + unsigned char bSpecific_1; + unsigned char bSpecific_2; + unsigned char APDU[ABDATA_SIZE]; +} __packed; +#endif diff --git a/drivers/usb/gadget/function/u_os_desc.h b/drivers/usb/gadget/function/u_os_desc.h new file mode 100644 index 0000000..947b7dd --- /dev/null +++ b/drivers/usb/gadget/function/u_os_desc.h @@ -0,0 +1,123 @@ +/* + * u_os_desc.h + * + * Utility definitions for "OS Descriptors" support + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __U_OS_DESC_H__ +#define __U_OS_DESC_H__ + +#include +#include + +#define USB_EXT_PROP_DW_SIZE 0 +#define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE 4 +#define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH 8 +#define USB_EXT_PROP_B_PROPERTY_NAME 10 +#define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH 10 +#define USB_EXT_PROP_B_PROPERTY_DATA 14 + +#define USB_EXT_PROP_RESERVED 0 +#define USB_EXT_PROP_UNICODE 1 +#define USB_EXT_PROP_UNICODE_ENV 2 +#define USB_EXT_PROP_BINARY 3 +#define USB_EXT_PROP_LE32 4 +#define USB_EXT_PROP_BE32 5 +#define USB_EXT_PROP_UNICODE_LINK 6 +#define USB_EXT_PROP_UNICODE_MULTI 7 + +static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset) +{ + return buf + offset; +} + +static inline u8 *usb_ext_prop_size_ptr(u8 *buf) +{ + return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE); +} + +static inline u8 *usb_ext_prop_type_ptr(u8 *buf) +{ + return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE); +} + +static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf) +{ + return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH); +} + +static inline u8 *usb_ext_prop_name_ptr(u8 *buf) +{ + return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME); +} + +static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off) +{ + return __usb_ext_prop_ptr(buf, + USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off); +} + +static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off) +{ + return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off); +} + +static inline void usb_ext_prop_put_size(u8 *buf, int dw_size) +{ + put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf)); +} + +static inline void usb_ext_prop_put_type(u8 *buf, int type) +{ + put_unaligned_le32(type, usb_ext_prop_type_ptr(buf)); +} + +static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl) +{ + int result; + + put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf)); + result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN, + (wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2); + if (result < 0) + return result; + + put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]); + + return pnl; +} + +static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data, + int data_len) +{ + put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl)); + memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len); +} + +static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string, + int data_len) +{ + int result; + put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl)); + result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN, + (wchar_t *) usb_ext_prop_data_ptr(buf, pnl), + data_len - 2); + if (result < 0) + return result; + + put_unaligned_le16(0, + &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]); + + return data_len; +} + +#endif /* __U_OS_DESC_H__ */