aboutsummaryrefslogtreecommitdiff
path: root/example-fs-bb48/usb_kl27z.c
diff options
context:
space:
mode:
Diffstat (limited to 'example-fs-bb48/usb_kl27z.c')
-rw-r--r--example-fs-bb48/usb_kl27z.c1034
1 files changed, 0 insertions, 1034 deletions
diff --git a/example-fs-bb48/usb_kl27z.c b/example-fs-bb48/usb_kl27z.c
deleted file mode 100644
index a7b8723..0000000
--- a/example-fs-bb48/usb_kl27z.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * usb_kl27z.c - USB driver for KL27Z
- *
- * Copyright (C) 2016 Flying Stone Technology
- * Author: NIIBE Yutaka <gniibe@fsij.org>
- *
- * This file is a part of Chopstx, a thread library for embedded.
- *
- * Chopstx 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 3 of the License, or
- * (at your option) any later version.
- *
- * Chopstx 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As additional permission under GNU GPL version 3 section 7, you may
- * distribute non-source form of the Program without the copy of the
- * GNU GPL normally required by section 4, provided you inform the
- * receipents of GNU GPL by a written offer.
- *
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "usb_lld.h"
-
-struct endpoint_ctl {
- uint32_t rx_odd: 1;
- uint32_t tx_odd: 1;
-};
-static struct endpoint_ctl ep[16];
-
-struct USB_CONF {
- const uint8_t PERID; /* Peripheral ID register */
- uint8_t rsvd0[3]; /* */
- const uint8_t IDCOMP; /* Peripheral ID Complement register */
- uint8_t rsvd1[3]; /* */
- const uint8_t REV; /* Peripheral Revision register */
- uint8_t rsvd2[3]; /* */
- volatile uint8_t ADDINFO; /* Peripheral Additional Info register */
-};
-static struct USB_CONF *const USB_CONF = (struct USB_CONF *const) 0x40072000;
-
-struct USB_CTRL0 {
- volatile uint8_t OTGCTL; /* OTG Control register */
-};
-static struct USB_CTRL0 *const USB_CTRL0 = (struct USB_CTRL0 *const)0x4007201c;
-
-struct USB_CTRL1 {
- volatile uint8_t ISTAT; /* Interrupt Status register */
- uint8_t rsvd5[3]; /* */
- volatile uint8_t INTEN; /* Interrupt Enable register */
- uint8_t rsvd6[3]; /* */
- volatile uint8_t ERRSTAT; /* Error Interrupt Status register */
- uint8_t rsvd7[3]; /* */
- volatile uint8_t ERREN; /* Error Interrupt Enable register */
- uint8_t rsvd8[3]; /* */
- volatile uint8_t STAT; /* Status register */
- uint8_t rsvd9[3]; /* */
- volatile uint8_t CTL; /* Control register */
- uint8_t rsvd10[3]; /* */
- volatile uint8_t ADDR; /* Address register */
- uint8_t rsvd11[3]; /* */
- volatile uint8_t BDTPAGE1; /* BDT Page register 1 */
- uint8_t rsvd12[3]; /* */
- volatile uint8_t FRMNUML; /* Frame Number register Low */
- uint8_t rsvd13[3]; /* */
- volatile uint8_t FRMNUMH; /* Frame Number register High */
- uint8_t rsvd14[11]; /* */
- volatile uint8_t BDTPAGE2; /* BDT Page Register 2 */
- uint8_t rsvd15[3]; /* */
- volatile uint8_t BDTPAGE3; /* BDT Page Register 3 */
-};
-static struct USB_CTRL1 *const USB_CTRL1 = (struct USB_CTRL1 *const)0x40072080;
-
-/* Interrupt source bits */
-#define USB_IS_STALL (1 << 7)
-#define USB_IS_RESUME (1 << 5)
-#define USB_IS_SLEEP (1 << 4)
-#define USB_IS_TOKDNE (1 << 3)
-#define USB_IS_SOFTOK (1 << 2)
-#define USB_IS_ERROR (1 << 1)
-#define USB_IS_USBRST (1 << 0)
-
-
-struct USB_ENDPT {
- volatile uint8_t EP; /* Endpoint Control register */
- uint8_t rsvd17[3];
-};
-static struct USB_ENDPT *const USB_ENDPT = (struct USB_ENDPT *const)0x400720c0;
-
-struct USB_CTRL2 {
- volatile uint8_t USBCTRL; /* USB Control register */
- uint8_t rsvd33[3]; /* */
- volatile uint8_t OBSERVE; /* USB OTG Observe register */
- uint8_t rsvd34[3]; /* */
- volatile uint8_t CONTROL; /* USB OTG Control register */
- uint8_t rsvd35[3]; /* */
- volatile uint8_t USBTRC0; /* USB Transceiver Control register 0 */
- uint8_t rsvd36[7]; /* */
- volatile uint8_t USBFRMADJUST; /* Frame Adjut Register */
-};
-static struct USB_CTRL2 *const USB_CTRL2 = (struct USB_CTRL2 *const)0x40072100;
-
-/* Buffer Descriptor */
-struct BD {
- volatile uint32_t ctrl;
- volatile void *buf;
-};
-/*
- uint32_t rsvd0 : 2;
- volatile uint32_t STALL: 1;
- volatile uint32_t DTS: 1;
-
- volatile uint32_t NINC: 1;
- volatile uint32_t KEEP: 1;
- volatile uint32_t DATA01: 1;
- volatile uint32_t OWN: 1;
-
- uint32_t rsvd1: 8;
- volatile uint32_t BC: 10;
- uint32_t rsvd2: 6;
-*/
-#define TOK_PID(ctrl) ((ctrl >> 2) & 0x0f)
-
-extern uint8_t __usb_bdt__;
-
-static struct BD *const BD_table = (struct BD *const)&__usb_bdt__;
-
-static uint8_t setup[8];
-/* bmRequestType, bRequest */
-/* Value: 2-byte */
-/* Index: 2-byte */
-/* Length: 2-byte */
-
-static void
-kl27z_usb_init (void)
-{
- int i;
-
- memset (ep, 0, sizeof (ep));
- memset (BD_table, 0, 16 * 2 * 2 * sizeof (struct BD));
-
- /* D+ pull up */
- USB_CTRL0->OTGCTL = 0x80;
-
- USB_CTRL1->ERREN = 0xff;
-
- USB_CTRL1->BDTPAGE1 = ((uint32_t)BD_table) >> 8;
- USB_CTRL1->BDTPAGE2 = ((uint32_t)BD_table) >> 16;
- USB_CTRL1->BDTPAGE3 = ((uint32_t)BD_table) >> 24;
-
- /* Not suspended, Pull-down disabled. */
- USB_CTRL2->USBCTRL = 0x00;
- /* DP Pullup in non-OTG device mode. */
- USB_CTRL2->CONTROL = 0x10;
-
- /* Disable all endpoints. */
- for (i = 0; i < 16; i++)
- USB_ENDPT[i].EP = 0;
-
- /*
- * Enable USB FS communication module, clearing all ODD-bits
- * for BDT.
- */
- USB_CTRL1->CTL = 0x03;
-
- /* ??? How we can ask re-enumeration? Is only hard RESET enough? */
-}
-
-static void
-kl27z_set_daddr (uint8_t daddr)
-{
- USB_CTRL1->ADDR = daddr;
-}
-
-static void
-kl27z_prepare_ep0_setup (void)
-{
- /* Endpoint 0, TX=0. */
- BD_table[ep[0].rx_odd].ctrl = 0x00080088; /* Len=8, OWN=1, DATA01=0, DTS=1 */
- BD_table[ep[0].rx_odd].buf = setup;
-
- BD_table[!ep[0].rx_odd].ctrl = 0x0000; /* OWN=0 */
- BD_table[!ep[0].rx_odd].buf = NULL;
-}
-
-static void
-kl27z_prepare_ep0_in (const void *buf, uint8_t len, int data01)
-{
- /* Endpoint 0, TX=1 *//* OWN=1, DTS=1 */
- BD_table[2+ep[0].tx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
- BD_table[2+ep[0].tx_odd].buf = (void *)buf;
-}
-
-static void
-kl27z_prepare_ep0_out (void *buf, uint8_t len, int data01)
-{
- /* Endpoint 0, TX=0 *//* OWN=1, DTS=1 */
- BD_table[ep[0].rx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
- BD_table[ep[0].rx_odd].buf = buf;
-}
-
-static int
-kl27z_ep_is_disabled (uint8_t n)
-{
- return (USB_ENDPT[n].EP == 0);
-}
-
-static int
-kl27z_ep_is_stall (uint8_t n)
-{
- return (USB_ENDPT[n].EP & 0x02) >> 1;
-}
-
-static void
-kl27z_ep_stall (uint8_t n)
-{
- USB_ENDPT[n].EP |= 0x02;
-}
-
-static void
-kl27z_ep_clear_stall (uint8_t n)
-{
- USB_ENDPT[n].EP &= ~0x02;
-}
-
-static void
-kl27z_ep_clear_dtog (int rx, uint8_t n)
-{
- uint32_t config;
-
- if (!kl27z_ep_is_stall (n))
- /* Just in case, when the endpoint is active */
- kl27z_ep_stall (n);
-
- if (rx)
- {
- config = BD_table[4*n+ep[n].rx_odd].ctrl;
-
- BD_table[4*n+!ep[n].rx_odd].ctrl &= ~(1 << 6);
- if ((config & 0x0080)) /* OWN already? */
- {
- /*
- * How to update BDT entry which is owned by USBFS seems to
- * be not clearly documented. It would be just OK to update
- * it as long as the endpoint is stalled (BDT entry is
- * actually not in use). We write 0 at first and then write
- * value with OWN, to avoid possible failure.
- */
- BD_table[4*n+ep[n].rx_odd].ctrl = 0;
- BD_table[4*n+ep[n].rx_odd].ctrl = (config & ~(1 << 6));
- }
- }
- else
- {
- config = BD_table[4*n+2+ep[n].tx_odd].ctrl;
-
- BD_table[4*n+2+!ep[n].tx_odd].ctrl &= ~(1 << 6);
- if ((config & 0x0080)) /* OWN already? */
- {
- BD_table[4*n+2+ep[n].tx_odd].ctrl = 0;
- BD_table[4*n+2+ep[n].tx_odd].ctrl = (config & ~(1 << 6));
- }
- }
-
- kl27z_ep_clear_stall (n);
-}
-
-#define USB_MAX_PACKET_SIZE 64 /* For FS device */
-
-enum STANDARD_REQUESTS {
- GET_STATUS = 0,
- CLEAR_FEATURE,
- RESERVED1,
- SET_FEATURE,
- RESERVED2,
- SET_ADDRESS,
- GET_DESCRIPTOR,
- SET_DESCRIPTOR,
- GET_CONFIGURATION,
- SET_CONFIGURATION,
- GET_INTERFACE,
- SET_INTERFACE,
- SYNCH_FRAME,
- TOTAL_REQUEST /* Total number of Standard request */
-};
-
-
-enum FEATURE_SELECTOR {
- ENDPOINT_STALL,
- DEVICE_REMOTE_WAKEUP
-};
-
-
-struct data_ctl {
- uint8_t *addr;
- uint16_t len;
- uint8_t require_zlp;
-};
-
-/* The state machine states of a control pipe */
-enum {
- WAIT_SETUP,
- IN_DATA,
- OUT_DATA,
- LAST_IN_DATA,
- WAIT_STATUS_IN,
- WAIT_STATUS_OUT,
- STALLED,
- PAUSE
-};
-
-struct device_ctl {
- /* control pipe state */
- uint8_t state;
-
- uint32_t tkdone;
- uint32_t reset;
- uint32_t error;
- uint32_t stall;
-
- uint32_t send;
- uint32_t recv;
-
- /* Device specific settings */
- uint8_t configuration;
- uint8_t feature;
-};
-
-static struct device_ctl device_ctl;
-static struct data_ctl data_ctl;
-
-static struct device_ctl *const dev_p = &device_ctl;
-static struct data_ctl *const data_p = &data_ctl;
-
-static void handle_transaction (uint8_t stat);
-
-void
-usb_lld_stall (int n)
-{
- kl27z_ep_stall (n);
-}
-
-
-void
-usb_lld_init (uint8_t feature)
-{
- dev_p->state = WAIT_SETUP;
- dev_p->tkdone = 0;
- dev_p->reset = 0;
- dev_p->error = 0;
- dev_p->stall = 0;
-
- usb_lld_set_configuration (0);
- dev_p->feature = feature;
-
- kl27z_set_daddr (0);
- kl27z_usb_init ();
-
- /* Enable the endpoint 0. */
- USB_ENDPT[0].EP = 0x0d;
-
- /* Clear Interrupt Status Register, and enable interrupt for USB */
- USB_CTRL1->ISTAT = 0xff; /* All clear */
-
- USB_CTRL1->INTEN = USB_IS_STALL | USB_IS_TOKDNE
- | USB_IS_ERROR | USB_IS_USBRST;
-}
-
-void
-usb_interrupt_handler (void)
-{
- uint8_t istat_value = USB_CTRL1->ISTAT;
- uint8_t stat = USB_CTRL1->STAT;
-
- if ((istat_value & USB_IS_USBRST))
- {
- USB_CTRL1->ISTAT = USB_IS_USBRST;
- usb_cb_device_reset ();
- dev_p->reset++;
- }
- else if ((istat_value & USB_IS_ERROR))
- { /* Clear Errors. */
- USB_CTRL1->ERRSTAT = USB_CTRL1->ERRSTAT;
- USB_CTRL1->ISTAT = USB_IS_ERROR;
- /*reset???*/
- dev_p->error++;
- }
- else if ((istat_value & USB_IS_TOKDNE))
- {
- handle_transaction (stat);
- dev_p->tkdone++;
- }
- else if ((istat_value & USB_IS_STALL))
- {
- /* ??? stat includes ep_num in this case ???: No, it doesn't */
-
- if (kl27z_ep_is_stall (0))
- { /* It's endpoint 0, recover from erorr. */
- dev_p->state = WAIT_SETUP;
- kl27z_ep_clear_stall (0);
- kl27z_prepare_ep0_setup ();
- }
-
- USB_CTRL1->ISTAT = USB_IS_STALL;
- dev_p->stall++;
- }
-}
-
-#define DATA0 0
-#define DATA1 1
-
-static void
-handle_datastage_out (uint8_t stat)
-{
- int odd = (stat >> 2)&1;
- int data01 = !((BD_table[odd].ctrl >> 6)&1);
- uint32_t len = (BD_table[odd].ctrl >> 16)&0x3ff;
-
- data_p->len -= len;
- data_p->addr += len;
-
- len = data_p->len;
- if (len > USB_MAX_PACKET_SIZE)
- len = USB_MAX_PACKET_SIZE;
-
- if (data_p->len == 0)
- {
- /* No more data to receive, proceed to send acknowledge for IN. */
- dev_p->state = WAIT_STATUS_IN;
- kl27z_prepare_ep0_in (setup, 0, DATA1);
- }
- else
- {
- dev_p->state = OUT_DATA;
- kl27z_prepare_ep0_out (data_p->addr, len, data01);
- }
-}
-
-static void
-handle_datastage_in (uint8_t stat)
-{
- int odd = (stat >> 2)&1;
- int data01 = !((BD_table[2+odd].ctrl >> 6)&1);
- uint32_t len = USB_MAX_PACKET_SIZE;
-
- if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
- {
- if (data_p->require_zlp)
- {
- data_p->require_zlp = 0;
-
- /* No more data to send. Send empty packet */
- kl27z_prepare_ep0_in (setup, 0, data01);
- }
- else
- {
- /* No more data to send, proceed to receive OUT acknowledge. */
- dev_p->state = WAIT_STATUS_OUT;
- kl27z_prepare_ep0_out (setup, 8, DATA1);
- }
-
- return;
- }
-
- dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA;
-
- if (len > data_p->len)
- len = data_p->len;
-
- kl27z_prepare_ep0_in (data_p->addr, len, data01);
- data_p->len -= len;
- data_p->addr += len;
-}
-
-typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
-
-static int
-std_none (uint8_t req, struct req_args *arg)
-{
- (void)req; (void)arg;
- return USB_UNSUPPORT;
-}
-
-static int
-std_get_status (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
- uint16_t status_info = 0;
-
- if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
- || USB_SETUP_SET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT)
- {
- if (arg->index == 0)
- {
- /* Get Device Status */
- uint8_t feature = dev_p->feature;
-
- /* Remote Wakeup enabled */
- if ((feature & (1 << 5)))
- status_info |= 2;
- else
- status_info &= ~2;
-
- /* Bus-powered */
- if ((feature & (1 << 6)))
- status_info |= 1;
- else /* Self-powered */
- status_info &= ~1;
-
- return usb_lld_reply_request (&status_info, 2, arg);
- }
- }
- else if (rcp == INTERFACE_RECIPIENT)
- {
- int r;
-
- if (dev_p->configuration == 0)
- return USB_UNSUPPORT;
-
- r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
- if (r != USB_SUCCESS)
- return USB_UNSUPPORT;
-
- return usb_lld_reply_request (&status_info, 2, arg);
- }
- else if (rcp == ENDPOINT_RECIPIENT)
- {
- uint8_t n = (arg->index & 0x0f);
-
- if ((arg->index & 0x70) || n == ENDP0)
- return USB_UNSUPPORT;
-
- if (kl27z_ep_is_disabled (n))
- return USB_UNSUPPORT;
-
- status_info = kl27z_ep_is_stall (n);
- return usb_lld_reply_request (&status_info, 2, arg);
- }
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_clear_feature (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_GET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT)
- {
- if (arg->len != 0 || arg->index != 0)
- return USB_UNSUPPORT;
-
- if (arg->value == DEVICE_REMOTE_WAKEUP)
- {
- dev_p->feature &= ~(1 << 5);
- return USB_SUCCESS;
- }
- }
- else if (rcp == ENDPOINT_RECIPIENT)
- {
- uint8_t n = (arg->index & 0x0f);
-
- if (dev_p->configuration == 0)
- return USB_UNSUPPORT;
-
- if (arg->len != 0 || (arg->index >> 8) != 0
- || arg->value != ENDPOINT_STALL || n == ENDP0)
- return USB_UNSUPPORT;
-
- if (kl27z_ep_is_disabled (n))
- return USB_UNSUPPORT;
-
- kl27z_ep_clear_dtog ((arg->index & 0x80) == 0, n);
-
- // event??
- return USB_SUCCESS;
- }
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_set_feature (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_GET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT)
- {
- if (arg->len != 0 || arg->index != 0)
- return USB_UNSUPPORT;
-
- if (arg->value == DEVICE_REMOTE_WAKEUP)
- {
- dev_p->feature |= 1 << 5;
- // event??
- return USB_SUCCESS;
- }
- }
- else if (rcp == ENDPOINT_RECIPIENT)
- {
- uint8_t n = (arg->index & 0x0f);
-
- if (dev_p->configuration == 0)
- return USB_UNSUPPORT;
-
- if (arg->len != 0 || (arg->index >> 8) != 0
- || arg->value != 0 || n == ENDP0)
- return USB_UNSUPPORT;
-
- if (kl27z_ep_is_disabled (n))
- return USB_UNSUPPORT;
-
- kl27z_ep_stall (n);
-
- // event??
- return USB_SUCCESS;
- }
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_set_address (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_GET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
- && arg->index == 0 && dev_p->configuration == 0)
- return USB_SUCCESS;
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_get_descriptor (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_SET (req))
- return USB_UNSUPPORT;
-
- return usb_cb_get_descriptor (rcp, (arg->value >> 8),
- (arg->value & 0xff), arg);
-}
-
-static int
-std_get_configuration (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- (void)arg;
- if (USB_SETUP_SET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT)
- return usb_lld_reply_request (&dev_p->configuration, 1, arg);
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_set_configuration (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_GET (req))
- return USB_UNSUPPORT;
-
- if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
- return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_get_interface (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_SET (req))
- return USB_UNSUPPORT;
-
- if (rcp == INTERFACE_RECIPIENT)
- {
- if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
- return USB_UNSUPPORT;
-
- if (dev_p->configuration == 0)
- return USB_UNSUPPORT;
-
- return usb_cb_interface (USB_GET_INTERFACE, arg);
- }
-
- return USB_UNSUPPORT;
-}
-
-static int
-std_set_interface (uint8_t req, struct req_args *arg)
-{
- uint8_t rcp = req & RECIPIENT;
-
- if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
- || arg->len != 0 || (arg->index >> 8) != 0
- || (arg->value >> 8) != 0 || dev_p->configuration == 0)
- return USB_UNSUPPORT;
-
- return usb_cb_interface (USB_SET_INTERFACE, arg);
-}
-
-
-static void
-handle_setup0 (void)
-{
- struct req_args *arg = (struct req_args *)&setup[2];
- int r = USB_UNSUPPORT;
- HANDLER handler;
-
- data_p->addr = NULL;
- data_p->len = 0;
- data_p->require_zlp = 0;
-
- if ((setup[0] & REQUEST_TYPE) == STANDARD_REQUEST)
- {
- if (setup[1] < TOTAL_REQUEST)
- {
- switch (setup[1])
- {
- case 0: handler = std_get_status; break;
- case 1: handler = std_clear_feature; break;
- case 3: handler = std_set_feature; break;
- case 5: handler = std_set_address; break;
- case 6: handler = std_get_descriptor; break;
- case 8: handler = std_get_configuration; break;
- case 9: handler = std_set_configuration; break;
- case 10: handler = std_get_interface; break;
- case 11: handler = std_set_interface; break;
- default: handler = std_none; break;
- }
-
- r = (*handler) (setup[0], arg);
- }
- }
- else
- r = usb_cb_setup (setup[0], setup[1], arg);
-
- if (r != USB_SUCCESS)
- dev_p->state = STALLED;
- else if (USB_SETUP_SET (setup[0]))
- {
- if (arg->len == 0)
- {
- /* Zero length packet for ACK. */
- kl27z_prepare_ep0_in (setup, 0, DATA1);
- dev_p->state = WAIT_STATUS_IN;
- }
- }
-}
-
-static void
-handle_in0 (uint8_t stat)
-{
- if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
- handle_datastage_in (stat);
- else if (dev_p->state == WAIT_STATUS_IN)
- { /* Control WRITE transfer done successfully. */
- uint16_t value = (setup[3]<<8) | setup[2];
-
- if ((setup[1] == SET_ADDRESS) &&
- ((setup[0] & (REQUEST_TYPE | RECIPIENT))
- == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
- {
- kl27z_set_daddr (value);
- usb_cb_handle_event (USB_EVENT_ADDRESS, value);
- ep[0].rx_odd = 0;
- }
- else
- usb_cb_ctrl_write_finish (setup[0], setup[1],
- (struct req_args *)&setup[2]);
-
- dev_p->state = WAIT_SETUP;
- kl27z_prepare_ep0_setup ();
- }
- else
- dev_p->state = STALLED;
-}
-
-static void
-handle_out0 (uint8_t stat)
-{
- if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA)
- /* Host aborts the control READ transfer before finish. */
- dev_p->state = STALLED;
- else if (dev_p->state == OUT_DATA)
- /* It's normal control WRITE transfer. */
- handle_datastage_out (stat);
- else if (dev_p->state == WAIT_STATUS_OUT)
- { /* Control READ transfer done successfully. */
- dev_p->state = WAIT_SETUP;
- kl27z_prepare_ep0_setup ();
- }
- else
- dev_p->state = STALLED;
-}
-
-static void
-handle_transaction (uint8_t stat)
-{
- int odd = (stat >> 2)&1;
- uint8_t ep_num = (stat >> 4);
-
- if (ep_num == 0)
- {
- if ((stat & 0x08) == 0)
- {
- ep[0].rx_odd ^= 1;
- if (TOK_PID (BD_table[odd].ctrl) == 0x0d)
- {
- handle_setup0 ();
- USB_CTRL1->ISTAT = USB_IS_TOKDNE;
- USB_CTRL1->CTL = 0x01; /* Clear TXSUSPENDTOKENBUSY. */
- }
- else
- {
- USB_CTRL1->ISTAT = USB_IS_TOKDNE;
- handle_out0 (stat);
- }
- }
- else
- {
- ep[0].tx_odd ^= 1;
- USB_CTRL1->ISTAT = USB_IS_TOKDNE;
- handle_in0 (stat);
- }
-
- if (dev_p->state == STALLED)
- kl27z_ep_stall (0);
- }
- else
- {
- if ((stat & 0x08) == 0)
- {
- dev_p->recv++;
- ep[ep_num].rx_odd ^= 1;
- usb_cb_rx_ready (ep_num);
- }
- else
- {
- /* XXX: Can be NAK. Check BDT if it's NAK or not. */
-
- dev_p->send++;
- ep[ep_num].tx_odd ^= 1;
- usb_cb_tx_done (ep_num);
- }
-
- USB_CTRL1->ISTAT = USB_IS_TOKDNE;
- }
-}
-
-void
-usb_lld_reset (uint8_t feature)
-{
- dev_p->feature = feature;
- usb_lld_set_configuration (0);
-
- /* Reset USB */
- USB_CTRL2->USBTRC0 = 0xc0;
-
- USB_CTRL1->CTL = 0x00; /* Disable USB FS communication module */
-
- dev_p->state = WAIT_SETUP;
- dev_p->tkdone = 0;
- dev_p->error = 0;
- dev_p->stall = 0;
-
- kl27z_set_daddr (0);
- kl27z_usb_init ();
-
- /* Clear Interrupt Status Register, and enable interrupt for USB */
- USB_CTRL1->ISTAT = 0xff; /* All clear */
-
- USB_CTRL1->INTEN = USB_IS_STALL | USB_IS_TOKDNE
- | USB_IS_ERROR | USB_IS_USBRST;
-}
-
-void
-usb_lld_setup_endpoint (int n, int rx_en, int tx_en)
-{
- if (n == 0)
- {
- /* Enable the endpoint 0. */
- USB_ENDPT[0].EP = 0x0d;
- kl27z_prepare_ep0_setup ();
- }
- else
- {
- /* Enable the endpoint. */
- USB_ENDPT[n].EP = (rx_en << 3)|(tx_en << 2)|0x11;
-
- /* Configure BDT entry so that it starts with DATA0. */
-
- /* RX */
- BD_table[4*n+ep[n].rx_odd].ctrl = 0x0000;
- BD_table[4*n+ep[n].rx_odd].buf = NULL;
- BD_table[4*n+!ep[n].rx_odd].ctrl = 0x0040;
- BD_table[4*n+!ep[n].rx_odd].buf = NULL;
-
- /* TX */
- BD_table[4*n+2+ep[n].tx_odd].ctrl = 0x0000;
- BD_table[4*n+2+ep[n].tx_odd].buf = NULL;
- BD_table[4*n+2+!ep[n].tx_odd].ctrl = 0x0040;
- BD_table[4*n+2+!ep[n].tx_odd].buf = NULL;
- }
-}
-
-
-void
-usb_lld_set_configuration (uint8_t config)
-{
- dev_p->configuration = config;
-}
-
-uint8_t
-usb_lld_current_configuration (void)
-{
- return dev_p->configuration;
-}
-
-void
-usb_lld_set_data_to_recv (void *p, size_t len)
-{
- data_p->addr = (uint8_t *)p;
- data_p->len = len;
- if (len > USB_MAX_PACKET_SIZE)
- len = USB_MAX_PACKET_SIZE;
-
- kl27z_prepare_ep0_out (p, len, DATA1);
- dev_p->state = OUT_DATA;
-}
-
-/*
- * BUF: Pointer to data memory. Data memory should not be allocated
- * on stack when BUFLEN > USB_MAX_PACKET_SIZE.
- *
- * BUFLEN: size of the data.
- */
-int
-usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *a)
-{
- uint32_t len_asked = a->len;
- uint32_t len;
-
- data_p->addr = (void *)buf;
- data_p->len = buflen;
-
- /* Restrict the data length to be the one host asks for */
- if (data_p->len > len_asked)
- data_p->len = len_asked;
-
- data_p->require_zlp = (data_p->len != 0
- && (data_p->len % USB_MAX_PACKET_SIZE) == 0);
-
- if (data_p->len < USB_MAX_PACKET_SIZE)
- {
- len = data_p->len;
- dev_p->state = LAST_IN_DATA;
- }
- else
- {
- len = USB_MAX_PACKET_SIZE;
- dev_p->state = IN_DATA;
- }
-
- if (len)
- kl27z_prepare_ep0_in (data_p->addr, len, DATA1);
-
- data_p->len -= len;
- data_p->addr += len;
-
- return USB_SUCCESS;
-}
-
-void
-usb_lld_rx_enable (int n, void *buf, size_t len)
-{
- int data01 = !((BD_table[4*n+!ep[n].rx_odd].ctrl >> 6)&1);
-
- BD_table[4*n+ep[n].rx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
- BD_table[4*n+ep[n].rx_odd].buf = buf;
-}
-
-int
-usb_lld_rx_data_len (int n)
-{
- return (BD_table[4*n+!ep[n].rx_odd].ctrl >> 16)&0x3ff;
-}
-
-
-void
-usb_lld_tx_enable (uint8_t n, const void *buf, size_t len)
-{
- int data01 = !((BD_table[4*n+2+!ep[n].tx_odd].ctrl >> 6)&1);
-
- BD_table[4*n+2+ep[n].tx_odd].ctrl = (len << 16) | 0x0088 | (data01 << 6);
- BD_table[4*n+2+ep[n].tx_odd].buf = (void *)buf;
-}
-
-int
-usb_lld_tx_result (int ep_num)
-{
- (void)ep_num;
- return 0; /* XXX: return -1 when NAK */
-}