s5pc110: USB Ethernet Gadget - enabled and fixed RNDIS mode
authorMarek Szyprowski <m.szyprowski@samsung.com>
Mon, 22 Feb 2010 11:18:48 +0000 (12:18 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Mon, 22 Feb 2010 11:18:48 +0000 (12:18 +0100)
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
drivers/usb/gadget/ether.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/rndis.h
drivers/usb/gadget/s3c_udc_otg.c
drivers/usb/gadget/s3c_udc_otg_xfer_dma.c

index 5baaf5a..cb1e62c 100644 (file)
 #include <net.h>
 /* #include <malloc.h> */
 #include <linux/ctype.h>
+#include <asm/unaligned.h>
 
 #include "gadget_chips.h"
 
-#define USB_NET_NAME "CDC Ethernet"
+#define USB_NET_NAME "USB Ethernet"
+
 #define dprintf(x, ...)
+//#define dprintf printf
 #undef INFO
 #define INFO(x, s...)  printf(s)
 #define dev_err(x, stuff...) printf(stuff)
@@ -40,7 +43,6 @@
 #define dev_warn dev_err
 #define DEBUG dev_err
 #define VDEBUG DEBUG
-#define likely
 #define atomic_read
 extern struct platform_data brd;
 #define spin_lock(x)
@@ -105,9 +107,6 @@ static const char driver_desc [] = DRIVER_DESC;
 
 #include "rndis.h"
 
-/* TODO: move it to some configuration file */
-#define CONFIG_USB_ETH_RNDIS
-
 #ifndef        CONFIG_USB_ETH_RNDIS
 #define rndis_uninit(x)                do{}while(0)
 #define rndis_deregister(c)    do{}while(0)
@@ -141,8 +140,8 @@ static inline int is_cdc(struct eth_dev *dev)
 #endif
 }
 
-#define        subset_active(dev)      (!is_cdc(dev))
-#define        cdc_active(dev)         ( is_cdc(dev))
+#define        subset_active(dev)      (!is_cdc(dev) && !rndis_active(dev))
+#define        cdc_active(dev)         ( is_cdc(dev) && !rndis_active(dev))
 
 #define DEFAULT_QLEN   2       /* double buffering by default */
 
@@ -279,6 +278,14 @@ static char *iSerialNumber;
 static char dev_addr[18];
 static char host_addr[18];
 
+
+void eth_connection_established(void)
+{
+       l_ethdev.network_started=1;
+       printf("connection established.\n");
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 /* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
@@ -921,6 +928,7 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
        int                                     result = 0;
        struct usb_gadget                       *gadget = dev->gadget;
 
+
 #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
        /* status endpoint used for (optionally) CDC */
        if (!subset_active(dev) && dev->status_ep) {
@@ -978,6 +986,21 @@ done:
                dev->out = NULL;
        }
 
+       /* activate non-CDC configs right away
+        * this isn't strictly according to the RNDIS spec
+        */
+       else if (!cdc_active (dev)) {
+               /* and open the tx floodgates */
+//             atomic_set (&dev->tx_qlen, 0);
+               dev->tx_qlen = 0;
+               if (rndis_active(dev)) {
+                       rndis_set_param_medium (dev->rndis_config,
+                                               NDIS_MEDIUM_802_3,
+                                               BITRATE(dev->gadget)/100);
+                       (void) rndis_signal_connect (dev->rndis_config);
+               }
+       }
+
        /* caller is responsible for cleanup on error */
        return result;
 }
@@ -1099,9 +1122,7 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
        /* issue the second notification if host reads the first */
        if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
                        && value == 0) {
-               char *src, *dst = req->buf + sizeof *event;
-               __le32 data;
-               int i;
+               __le32  val, *data = req->buf + sizeof *event;
 
                event->bmRequestType = 0xA1;
                event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
@@ -1110,15 +1131,9 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
                event->wLength = __constant_cpu_to_le16 (8);
 
                /* SPEED_CHANGE data is up/down speeds in bits/sec */
-
-               data = cpu_to_le32 (BITRATE (dev->gadget));
-
-               src = &data;
-               for (i=0; i<4; i++)
-                       *dst++ = *src++;
-               src = &data;
-               for (i=0; i<4; i++)
-                       *dst++ = *src++;
+               val = cpu_to_le32 (BITRATE (dev->gadget));
+               put_unaligned_le32(val, &data[0]);
+               put_unaligned_le32(val, &data[1]);
        
                req->length = STATUS_BYTECOUNT;
                value = usb_ep_queue (ep, req, GFP_ATOMIC);
@@ -1130,10 +1145,7 @@ static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
                        event->bNotificationType, value);
                if (event->bNotificationType==
                                USB_CDC_NOTIFY_SPEED_CHANGE)
-               {
-                       l_ethdev.network_started=1;
-                       printf("USB network up!\n");
-               }
+                       eth_connection_established();
        }
        req->context = NULL;
        dprintf("done\n");
@@ -1239,11 +1251,6 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
         */
 
        dprintf("eth_setup:...\n");
-       if (rndis_active(dev)) {
-               rndis_set_param_medium(dev->rndis_config,
-                                      NDIS_MEDIUM_802_3, 0);
-               (void) rndis_signal_connect (dev->rndis_config);
-       }
 
        req->complete = eth_setup_complete;
        switch (ctrl->bRequest) {
@@ -1542,22 +1549,21 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
        int length;
 
        dprintf("%s\n", __func__);
-       dprintf("rx status %d\n", req->status);
+       dprintf("rx status %d, len %d\n", req->status, req->actual);
 
        packet_received=1;
        if (!req)
                return;
 
        buf = req->buf;
-       length = req->length;
+       length = req->actual;
        if (rndis_active(dev)) {
-               if(rndis_rm_hdr(&buf, &length))
+               if(rndis_rm_hdr(buf, &length))
                        dprintf("%s: incorrect RNDIS packet\n",
                                __func__);
                /* XXX: what to do if RNDIS fails !?!? */
        }
-       req->buf = buf;
-       req->length = length;
+       req->actual = length;
        dev->rx_req=req;
 }
 
@@ -1934,6 +1940,7 @@ static int eth_bind(struct usb_gadget *gadget)
 #ifndef        CONFIG_USB_ETH_RNDIS
        rndis = 0;
 #endif
+#if 0
        /* Because most host side USB stacks handle CDC Ethernet, that
         * standard protocol is _strongly_ preferred for interop purposes.
         * (By everyone except Microsoft.)
@@ -1956,7 +1963,7 @@ static int eth_bind(struct usb_gadget *gadget)
                 */
                cdc = 0;
        }
-
+#endif
        gcnum = usb_gadget_controller_number (gadget);
        if (gcnum >= 0)
                device_desc.bcdDevice = cpu_to_le16 (0x0300 + gcnum);
@@ -1971,6 +1978,12 @@ static int eth_bind(struct usb_gadget *gadget)
                return -ENODEV;
        }
 
+       /* support optional vendor/distro customization */
+#if defined(CONFIG_USB_CDC_VENDOR_ID) && defined(CONFIG_USB_CDC_PRODUCT_ID)
+       device_desc.idVendor = cpu_to_le16(CONFIG_USB_CDC_VENDOR_ID);
+       device_desc.idProduct = cpu_to_le16(CONFIG_USB_CDC_PRODUCT_ID);
+#endif
+
        /* If there's an RNDIS configuration, that's what Windows wants to
         * be using ... so use these product IDs here and in the "linux.inf"
         * needed to install MSFT drivers.  Current Linux kernels will use
@@ -1984,6 +1997,12 @@ static int eth_bind(struct usb_gadget *gadget)
                        __constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
                sprintf (product_desc, "RNDIS/%s", driver_desc);
 
+#if defined(CONFIG_USB_RNDIS_VENDOR_ID) && defined(CONFIG_USB_RNDIS_PRODUCT_ID)
+       device_desc.idVendor = cpu_to_le16(CONFIG_USB_RNDIS_VENDOR_ID);
+       device_desc.idProduct = cpu_to_le16(CONFIG_USB_RNDIS_PRODUCT_ID);
+#endif
+
+
        /* CDC subset ... recognized by Linux since 2.4.10, but Windows
         * drivers aren't widely available.  (That may be improved by
         * supporting one submode of the "SAFE" variant of MDLM.)
@@ -1995,11 +2014,6 @@ static int eth_bind(struct usb_gadget *gadget)
                        __constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
        }
 
-       /* support optional vendor/distro customization */
-#if defined(CONFIG_USB_CDC_VENDOR_ID) && defined(CONFIG_USB_CDC_PRODUCT_ID)
-       device_desc.idVendor = cpu_to_le16(CONFIG_USB_CDC_VENDOR_ID);
-       device_desc.idProduct = cpu_to_le16(CONFIG_USB_CDC_PRODUCT_ID);
-#endif
        if (bcdDevice)
                device_desc.bcdDevice = cpu_to_le16(bcdDevice);
        if (iManufacturer)
@@ -2107,7 +2121,6 @@ autoconf_fail:
 
        dev->cdc = cdc;
        dev->zlp = zlp;
-       dev->rndis = rndis;
 
        dev->in_ep = in_ep;
        dev->out_ep = out_ep;
@@ -2143,6 +2156,7 @@ autoconf_fail:
        /* use PKTSIZE (or aligned... from u-boot) and set
         * wMaxSegmentSize accordingly*/
        dev->mtu = PKTSIZE_ALIGN; /* RNDIS does not like this, only 1514, TODO*/
+       dev->net->mtu = 1500; /* hack for RNDIS OID_GEN_MAXIMUM_FRAME_SIZE */
 
        /* preallocate control message data and buffer */
        dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
@@ -2204,12 +2218,11 @@ fail0:
                        goto fail;
                }
 
-               /* XXX warkaround for missing stats in eth_dev structure */
-               static struct eth_device_stats dev_stats;
                /* these set up a lot of the OIDs that RNDIS needs */
                rndis_set_host_mac (dev->rndis_config, dev->host_mac);
+
                if (rndis_set_param_dev (dev->rndis_config, dev->net,
-                                        &dev_stats, &dev->cdc_filter))
+                                        NULL, &dev->cdc_filter))
                        goto fail0;
                if (rndis_set_param_vendor(dev->rndis_config, vendorID,
                                        manufacturer))
@@ -2261,6 +2274,9 @@ static int usb_eth_init(struct eth_device* netdev, bd_t* bd)
        if (getenv("cdc_connect_timeout"))
                timeout = simple_strtoul(getenv("cdc_connect_timeout"),
                                                NULL, 10) * CONFIG_SYS_HZ;
+
+       printf("Initializing USB...");
+
        ts = get_timer(0);
        while (!l_ethdev.network_started)
        {
@@ -2270,13 +2286,26 @@ static int usb_eth_init(struct eth_device* netdev, bd_t* bd)
                        printf("The remote end did not respond in time.\n");
                        goto fail;
                }
+
                irq_res = usb_gadget_handle_interrupts();
 
                /* hack nice progress display */
                if (irq_res && !l_ethdev.network_started)
-                       printf(".");    
+                       printf(".");
        }
 
+       if (rndis_active(dev)) {
+               printf("Waiting for RNDIS link...");
+
+               /* wait for RNDIS to setup */
+               ts = get_timer(0);
+               while (get_timer(ts) < 250)
+               {
+                       if (usb_gadget_handle_interrupts())
+                               printf(".");
+               }
+               printf("\n");
+       }
        rx_submit (dev, dev->rx_req, 0);
        return 0;
 fail:
@@ -2355,7 +2384,7 @@ static int usb_eth_recv(struct eth_device* netdev)
                if (dev->rx_req)
                {
                        void *data = dev->rx_req->buf;
-                       int len = dev->rx_req->length;
+                       int len = dev->rx_req->actual;
                        NetReceive(data, len);
                        packet_received=0;
                        rx_submit (dev, dev->rx_req, 0);
@@ -2399,7 +2428,7 @@ int usb_eth_initialize(bd_t *bi)
        int status = 0;
        struct eth_device *netdev=&l_netdev;
 
-       sprintf(netdev->name, "USB CDC Ethernet");
+       sprintf(netdev->name, USB_NET_NAME);
 
        netdev->init = usb_eth_init;
        netdev->send = usb_eth_send;
index 40bdf90..f7689c9 100644 (file)
@@ -48,7 +48,7 @@
 #define ETH_ALEN       6 /* copied from ether.c */
 
 #define netif_running(...)     1
-#define netif_carrier_on(...) do { } while(0)
+#define netif_carrier_on(...) eth_connection_established()
 #define netif_wake_queue(...) do { } while(0)
 #define netif_carrier_off(...) do { } while(0)
 #define netif_stop_queue(...) do { } while(0)
  * and will be happier if you provide the host_addr module parameter.
  */
 
-#if 0
-static int rndis_debug = 0;
-module_param (rndis_debug, int, 0);
-MODULE_PARM_DESC (rndis_debug, "enable debugging");
-#else
 #define rndis_debug            0
-#endif
 
 #define DBG(str,args...) do { \
        if (rndis_debug) \
@@ -830,10 +824,9 @@ static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
                return -ENOMEM;
        resp = (rndis_init_cmplt_type *) r->buf;
 
-       resp->MessageType = __constant_cpu_to_le32 (
-                       REMOTE_NDIS_INITIALIZE_CMPLT);
+       resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_INITIALIZE_CMPLT);
        resp->MessageLength = __constant_cpu_to_le32 (52);
-       resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+       resp->RequestID = get_unaligned_le32(&buf->RequestID); /* Still LE in msg buffer */
        resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
        resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION);
        resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION);
@@ -861,7 +854,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
        rndis_query_cmplt_type *resp;
        rndis_resp_t            *r;
 
-       // DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
+       // DBG("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID));
        if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
 
        /*
@@ -877,12 +870,12 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
        resp = (rndis_query_cmplt_type *) r->buf;
 
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
-       resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+       resp->RequestID = get_unaligned_le32(&buf->RequestID); /* Still LE in msg buffer */
 
-       if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
-                       le32_to_cpu(buf->InformationBufferOffset)
+       if (gen_ndis_query_resp (configNr, get_unaligned_le32(&buf->OID),
+                       get_unaligned_le32(&buf->InformationBufferOffset)
                                        + 8 + (u8 *) buf,
-                       le32_to_cpu(buf->InformationBufferLength),
+                       get_unaligned_le32(&buf->InformationBufferLength),
                        r)) {
                /* OID not supported */
                resp->Status = __constant_cpu_to_le32 (
@@ -913,8 +906,8 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
                return -ENOMEM;
        resp = (rndis_set_cmplt_type *) r->buf;
 
-       BufLength = le32_to_cpu (buf->InformationBufferLength);
-       BufOffset = le32_to_cpu (buf->InformationBufferOffset);
+       BufLength = get_unaligned_le32(&buf->InformationBufferLength);
+       BufOffset = get_unaligned_le32(&buf->InformationBufferOffset);
 
 #ifdef VERBOSE
        DBG("%s: Length: %d\n", __func__, BufLength);
@@ -930,8 +923,8 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
 
        resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
        resp->MessageLength = __constant_cpu_to_le32 (16);
-       resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-       if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
+       resp->RequestID = get_unaligned_le32(&buf->RequestID); /* Still LE in msg buffer */
+       if (gen_ndis_set_resp (configNr, get_unaligned_le32(&buf->OID),
                        ((u8 *) buf) + 8 + BufOffset, BufLength, r))
                resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
        else
@@ -983,7 +976,7 @@ static int rndis_keepalive_response (int configNr,
        resp->MessageType = __constant_cpu_to_le32 (
                        REMOTE_NDIS_KEEPALIVE_CMPLT);
        resp->MessageLength = __constant_cpu_to_le32 (16);
-       resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+       resp->RequestID = get_unaligned_le32(&buf->RequestID); /* Still LE in msg buffer */
        resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
        if (rndis_per_dev_params [configNr].ack)
@@ -1192,7 +1185,7 @@ int rndis_set_param_dev (u8 configNr, struct eth_device *dev,
                         u16 *cdc_filter)
 {
        DBG("%s:\n", __func__ );
-       if (!dev || !stats) return -1;
+//     if (!dev || !stats) return -1;
        if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
        rndis_per_dev_params [configNr].dev = dev;
@@ -1249,6 +1242,7 @@ rndis_packet_buffer *rndis_packet_create(void *data, int len)
 
        memcpy(rndis_buffer.data + header_size, data, len);
 
+       DBG("Created RNDIS packet of size %d data offset %d total %d\n", len, header_size, total_size);
        rndis_buffer.len = total_size;
        rndis_buffer.in_use = 1;
        return &rndis_buffer;
@@ -1334,11 +1328,15 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length)
        return r;
 }
 
-int rndis_rm_hdr(void **data, int *len)
+int rndis_rm_hdr(void *data, int *len)
 {
+       int i;
+       char *dst = data;
+       char *src = data;
        /* tmp points to a struct rndis_packet_msg_type */
-       __le32          *tmp = (void *) *data;
+       __le32          *tmp = (void *) data;
        int DataOffset, DataLength;
+       DBG("%s, %d\n", __FUNCTION__, __LINE__);
 
        /* MessageType, MessageLength */
        if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
@@ -1348,11 +1346,16 @@ int rndis_rm_hdr(void **data, int *len)
        DataOffset = get_unaligned_le32(tmp++);
        DataLength = get_unaligned_le32(tmp++);
 
+       src += DataOffset + 8;
        if (DataLength > *len)
                return -EOVERFLOW;
        
+       for (i=0; i<DataLength; i++)
+               dst[i] = src[i];
+
        *len = DataLength;
-       *data = *data + DataOffset;
+
+       DBG("RNDIS pkt: offset %d size %d, src %x dst %x\n", DataOffset, DataLength, src, dst);
 
        return 0;
 }
index 98ff82e..e047bd8 100644 (file)
@@ -274,7 +274,7 @@ int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
 void rndis_add_hdr (struct sk_buff *skb);
 int rndis_rm_hdr (struct sk_buff *skb);
 #endif
-int rndis_rm_hdr(void **data, int *len);
+int rndis_rm_hdr(void *data, int *len);
 
 u8   *rndis_get_next_response (int configNr, u32 *length);
 void rndis_free_response (int configNr, u8 *buf);
index f728fa7..fb0cf1e 100644 (file)
@@ -248,11 +248,17 @@ void otg_phy_init(void)
 
 void otg_phy_off(void)
 {
-       writel(readl(S3C_USBOTG_PHYPWR)|(0x3<<3), S3C_USBOTG_PHYPWR);
+       /* reset controller just in case */
+       writel(0x1, S3C_USBOTG_RSTCON);
+       udelay(20);
+       writel(0x0, S3C_USBOTG_RSTCON);
+       udelay(20);
+
+       writel(readl(S3C_USBOTG_PHYPWR)|(0x3<<3)|(0x1), S3C_USBOTG_PHYPWR);
        writel(readl(S5PC110_USB_PHY_CON)&~(1<<0), S5PC110_USB_PHY_CON);
 //     writel(readl(S5P_USB_PHY_CONTROL)&~(1<<0), S5P_USB_PHY_CONTROL);
 
-       writel((readl(S3C_USBOTG_PHYPWR)&~(0x3<<3)&~(0x1<<0)),S3C_USBOTG_PHYPWR);
+//     writel((readl(S3C_USBOTG_PHYPWR)&~(0x3<<3)&~(0x1<<0)),S3C_USBOTG_PHYPWR);
        writel((readl(S3C_USBOTG_PHYCLK)&~(0x5<<2)),S3C_USBOTG_PHYCLK);
 
        udelay(10000);
@@ -584,6 +590,11 @@ static void reconfig_usbd(void)
        writel(DEPCTL_EPDIS|DEPCTL_SNAK|(0<<0), S3C_UDC_OTG_DOEPCTL(EP0_CON));
        writel(DEPCTL_EPDIS|DEPCTL_SNAK|(0<<0), S3C_UDC_OTG_DIEPCTL(EP0_CON));
 
+       for (i = 1; i < S3C_MAX_ENDPOINTS; i++) {
+               writel(DEPCTL_EPDIS|DEPCTL_SNAK, S3C_UDC_OTG_DOEPCTL(i));
+               writel(DEPCTL_EPDIS|DEPCTL_SNAK, S3C_UDC_OTG_DIEPCTL(i));
+       }
+
        /* 8. Unmask EPO interrupts*/
        writel( ((1<<EP0_CON)<<DAINT_OUT_BIT)|(1<<EP0_CON), S3C_UDC_OTG_DAINTMSK);
 
index 95c6015..41efe5d 100644 (file)
@@ -33,6 +33,8 @@ static int clear_feature_flag = 0;
 #define GET_MAX_LUN_REQUEST    0xFE
 #define BOT_RESET_REQUEST      0xFF
 
+#if 0
+
 /* TEST MODE in set_feature request */
 #define TEST_SELECTOR_MASK     0xFF
 #define TEST_PKT_SIZE          53
@@ -46,6 +48,8 @@ static u8 test_pkt[TEST_PKT_SIZE] = {
        0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E                            //{JKKKKKKK x 10},JK
 };
 
+#endif
+
 void s3c_udc_ep_set_stall(struct s3c_ep *ep);
 
 static inline void s3c_udc_ep0_zlp(void)
@@ -980,7 +984,7 @@ void s3c_udc_ep_activate(struct s3c_ep *ep)
        if (!(ep_ctrl & DEPCTL_USBACTEP)) {
                ep_ctrl = (ep_ctrl & ~DEPCTL_TYPE_MASK)| (ep->bmAttributes << DEPCTL_TYPE_BIT);
                ep_ctrl = (ep_ctrl & ~DEPCTL_MPS_MASK) | (ep->ep.maxpacket << DEPCTL_MPS_BIT);
-               ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP);
+               ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP | DEPCTL_SNAK);
 
                if (ep_is_in(ep)) {
                        writel(ep_ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));
@@ -1056,6 +1060,8 @@ static int s3c_udc_clear_feature(struct usb_ep *_ep)
        return 0;
 }
 
+#if 0
+
 /* Set into the test mode for Test Mode set_feature request */
 static inline void set_test_mode(void)
 {
@@ -1117,6 +1123,8 @@ static inline void set_test_mode(void)
        }
 }
 
+#endif
+
 static int s3c_udc_set_feature(struct usb_ep *_ep)
 {
        struct s3c_ep   *ep;
@@ -1138,12 +1146,12 @@ static int s3c_udc_set_feature(struct usb_ep *_ep)
                case USB_DEVICE_REMOTE_WAKEUP:
                        DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_REMOTE_WAKEUP\n");
                        break;
-
+#if 0
                case USB_DEVICE_TEST_MODE:
                        DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_TEST_MODE\n");
                        set_test_mode();
                        break;
-
+#endif
                case USB_DEVICE_B_HNP_ENABLE:
                        DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
                        break;
@@ -1205,6 +1213,22 @@ static void s3c_ep0_setup(struct s3c_udc *dev)
                        (usb_ctrl->bRequestType & USB_DIR_IN) ? "IN" : "OUT", usb_ctrl->bRequest,
                        usb_ctrl->wLength, usb_ctrl->wValue, usb_ctrl->wIndex);
 
+#ifdef DEBUG_S3C_UDC
+       {
+               int i, len = sizeof(*usb_ctrl);
+               char *p = usb_ctrl;
+
+               printf("pkt = ");
+               for (i=0; i<len; i++) {
+                       printf("%02x", ((u8*)p)[i]);
+                       if ((i & 7) == 7)
+                               printf(" ");
+               }
+               printf("\n");
+       }
+#endif
+
+
        if (usb_ctrl->bRequest == GET_MAX_LUN_REQUEST && usb_ctrl->wLength != 1) {
                DEBUG_SETUP("\t%s:GET_MAX_LUN_REQUEST:invalid wLength = %d, setup returned\n",
                        __func__, usb_ctrl->wLength);