mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
make udc work
This commit is contained in:
@@ -73,11 +73,13 @@ static void setup ():
|
||||
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
|
||||
|
||||
Kernel::Num start ():
|
||||
// Set up lcd first
|
||||
Kernel::schedule ()
|
||||
kdebug ("init started\n")
|
||||
setup ()
|
||||
kdebug ("init set up\n")
|
||||
while true:
|
||||
kdebug ("init waiting\n")
|
||||
Kernel::wait ()
|
||||
kdebug ("init done waiting\n")
|
||||
switch Kernel::recv.protected_data.value ():
|
||||
case KBD:
|
||||
unsigned code = Kernel::recv.data[0].l
|
||||
|
||||
@@ -130,14 +130,13 @@ class Udc:
|
||||
char configuration
|
||||
unsigned size
|
||||
char const *ptr
|
||||
unsigned send_next (unsigned old_csr)
|
||||
unsigned vendor (unsigned old_csr, Setup *s)
|
||||
unsigned get_descriptor (unsigned old_csr, unsigned type, unsigned idx, unsigned len)
|
||||
bool vendor (Setup *s)
|
||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||
bool handle_setup (Setup *s)
|
||||
public:
|
||||
void init ()
|
||||
void log (unsigned c)
|
||||
void interrupt ()
|
||||
unsigned handle_setup (unsigned old_csr, Setup *s)
|
||||
|
||||
Udc::Device const Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0x601a, 0x4740, 0x100, 1, 2, 0, 1 }
|
||||
Udc::my_config const Udc::config_descriptor = {
|
||||
@@ -150,6 +149,7 @@ Udc::my_config const Udc::config_descriptor = {
|
||||
Udc::String <7> const Udc::s_manufacturer = { sizeof (String <7>), String <7>::Type, { 'I', 'n', 'g', 'e', 'n', 'i', 'c' } }
|
||||
Udc::String <22> const Udc::s_product = { sizeof (String <22>), String <22>::Type, { 'J', 'Z', '4', '7', '4', '0', ' ', 'U', 'S', 'B', ' ', 'B', 'o', 'o', 't', ' ', 'D', 'e', 'v', 'i', 'c', 'e'} }
|
||||
void Udc::init ():
|
||||
kdebug ("udc: init\n")
|
||||
state = IDLE
|
||||
configuration = 0
|
||||
size = 0
|
||||
@@ -162,36 +162,32 @@ void Udc::init ():
|
||||
UDC_INTRUSB = UDC_INTR_RESET
|
||||
// enable interrupts on endpoint 0.
|
||||
UDC_INTRINE |= 1 << 0
|
||||
UDC_INDEX = 0
|
||||
|
||||
unsigned Udc::send_next (unsigned old_csr):
|
||||
for unsigned i = 0; size > 0 && i < max_packet_size0; ++i, --size:
|
||||
// Use 8-bit transfers to avoid problems with alignment.
|
||||
REG8 (UDC_FIFO_EP0) = *ptr++
|
||||
if size:
|
||||
state = TX
|
||||
return (old_csr | UDC_CSR0_INPKTRDY) & ~UDC_CSR0_DATAEND
|
||||
else:
|
||||
state = IDLE
|
||||
return old_csr | UDC_CSR0_INPKTRDY
|
||||
|
||||
unsigned Udc::vendor (unsigned old_csr, Setup *s):
|
||||
bool Udc::vendor (Setup *s):
|
||||
kdebug ("udc: vendor\n")
|
||||
if s->request_type & 0x80:
|
||||
ptr = "abcdefgh"
|
||||
kdebug ("udc: vendorsend\n")
|
||||
static char const *name = "abcdefgh"
|
||||
ptr = name
|
||||
size = 8
|
||||
return send_next (old_csr)
|
||||
return old_csr
|
||||
state = TX
|
||||
return true
|
||||
kdebug ("udc: vendorrecv\n")
|
||||
return true
|
||||
|
||||
unsigned Udc::get_descriptor (unsigned old_csr, unsigned type, unsigned idx, unsigned len):
|
||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
kdebug ("udc: getdesc\n")
|
||||
switch type:
|
||||
case Configuration::Type:
|
||||
if idx != 1:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&config_descriptor)
|
||||
size = (len < sizeof (config_descriptor) ? len : sizeof (config_descriptor))
|
||||
break
|
||||
case Device::Type:
|
||||
if idx != 0:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&device_descriptor)
|
||||
size = (len < sizeof (device_descriptor) ? len : sizeof (device_descriptor))
|
||||
break
|
||||
@@ -207,13 +203,23 @@ unsigned Udc::get_descriptor (unsigned old_csr, unsigned type, unsigned idx, uns
|
||||
size = (len < sizeof (s_product) ? len : sizeof (s_product))
|
||||
break
|
||||
default:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
break
|
||||
default:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return send_next (old_csr)
|
||||
return false
|
||||
state = TX
|
||||
return true
|
||||
|
||||
unsigned Udc::handle_setup (unsigned old_csr, Setup *s):
|
||||
bool Udc::handle_setup (Setup *s):
|
||||
kdebug ("udc: setup: type=")
|
||||
kdebug_num (s->request_type)
|
||||
kdebug ("; request=")
|
||||
kdebug_num (s->request)
|
||||
kdebug ("; value=")
|
||||
kdebug_num (s->value)
|
||||
kdebug ("; index=")
|
||||
kdebug_num (s->index)
|
||||
kdebug ("\n")
|
||||
switch s->request_type:
|
||||
case STANDARD_TO_DEVICE:
|
||||
switch s->request:
|
||||
@@ -222,49 +228,55 @@ unsigned Udc::handle_setup (unsigned old_csr, Setup *s):
|
||||
break
|
||||
case SET_CONFIGURATION:
|
||||
if s->value >= 2:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
configuration = s->value
|
||||
break
|
||||
case SET_INTERFACE:
|
||||
if s->value != 0:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
break
|
||||
default:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
break
|
||||
case STANDARD_FROM_DEVICE:
|
||||
switch s->request:
|
||||
case GET_STATUS:
|
||||
ptr = "\0\0"
|
||||
size = (s->length < 2 ? s->length : 2)
|
||||
return send_next (old_csr)
|
||||
state = TX
|
||||
break
|
||||
case GET_DESCRIPTOR:
|
||||
return get_descriptor (old_csr, (s->value >> 8) & 0xff, s->value & 0xff, s->length)
|
||||
return get_descriptor ((s->value >> 8) & 0xff, s->value & 0xff, s->length)
|
||||
case GET_CONFIGURATION:
|
||||
ptr = &configuration
|
||||
size = (s->length < 1 ? s->length : 1)
|
||||
return send_next (old_csr)
|
||||
state = TX
|
||||
break
|
||||
case GET_INTERFACE:
|
||||
ptr = "\0"
|
||||
size = (s->length < 1 ? s->length : 1)
|
||||
return send_next (old_csr)
|
||||
state = TX
|
||||
break
|
||||
default:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return false
|
||||
break
|
||||
case VENDOR_TO_DEVICE:
|
||||
case VENDOR_FROM_DEVICE:
|
||||
return vendor (old_csr, s)
|
||||
return vendor (s)
|
||||
default:
|
||||
return old_csr | UDC_CSR0_SENDSTALL
|
||||
return old_csr
|
||||
return false
|
||||
return true
|
||||
|
||||
void Udc::interrupt ():
|
||||
kdebug ("udc: inter\n")
|
||||
unsigned i = UDC_INTRUSB
|
||||
if i & UDC_INTR_RESET:
|
||||
kdebug ("udc: reset\n")
|
||||
state = IDLE
|
||||
return
|
||||
i = UDC_INTRIN
|
||||
if i & (1 << 0):
|
||||
kdebug ("udc: ep0\n")
|
||||
// Interrupt on endpoint 0.
|
||||
unsigned csr = UDC_CSR0
|
||||
if csr & UDC_CSR0_SENTSTALL:
|
||||
@@ -275,39 +287,68 @@ void Udc::interrupt ():
|
||||
state = IDLE
|
||||
switch state:
|
||||
case IDLE:
|
||||
kdebug ("udc: idle\n")
|
||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||
break
|
||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_DATAEND
|
||||
return
|
||||
kdebug ("udc: packet\n")
|
||||
union { unsigned d[2]; Setup s; } packet
|
||||
packet.d[0] = UDC_FIFO_EP0
|
||||
packet.d[1] = UDC_FIFO_EP0
|
||||
csr = handle_setup (csr, &packet.s)
|
||||
UDC_CSR0 = csr
|
||||
break
|
||||
packet.d[0] = UDC_FIFO (0)
|
||||
packet.d[1] = UDC_FIFO (0)
|
||||
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||
if !handle_setup (&packet.s):
|
||||
csr |= UDC_CSR0_SENDSTALL
|
||||
break
|
||||
if size == 0:
|
||||
return
|
||||
// Fall through.
|
||||
case TX:
|
||||
UDC_CSR0 = send_next (UDC_CSR0 | UDC_CSR0_DATAEND)
|
||||
kdebug ("udc: send next:")
|
||||
unsigned i
|
||||
for i = 0; (size & ~3) > 0 && i < max_packet_size0; i += 4, size -= 4:
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
kdebug_num (ptr[i], 2)
|
||||
UDC_FIFO (0) = *(unsigned *)ptr
|
||||
ptr += 4
|
||||
for ; size > 0 && i < max_packet_size0; ++i, --size:
|
||||
kdebug_num (*ptr, 2)
|
||||
UDC_FIFO8 (0) = *ptr++
|
||||
kdebug ("\n")
|
||||
if i == max_packet_size0:
|
||||
csr |= UDC_CSR0_INPKTRDY
|
||||
else:
|
||||
state = IDLE
|
||||
csr |= UDC_CSR0_INPKTRDY | UDC_CSR0_DATAEND
|
||||
break
|
||||
case RX:
|
||||
// Not supported.
|
||||
UDC_CSR0 |= UDC_CSR0_SENDSTALL
|
||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL
|
||||
state = IDLE
|
||||
break
|
||||
UDC_CSR0 = csr
|
||||
|
||||
void Udc::log (unsigned c):
|
||||
kdebug ("udc: log\n")
|
||||
|
||||
Kernel::Num start ():
|
||||
map_udc ()
|
||||
Udc udc
|
||||
|
||||
kdebug ("udc: start\n")
|
||||
udc.init ()
|
||||
kdebug ("udc: done init\n")
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LOG)
|
||||
kdebug ("udc: made cap\n")
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
kdebug ("udc: registered cap\n")
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
kdebug ("udc: registered interrupt\n")
|
||||
while true:
|
||||
kdebug ("udc: waiting\n")
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_UDC:
|
||||
udc.interrupt ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
break
|
||||
case Init::LOG:
|
||||
udc.log (Kernel::recv.data[0].l)
|
||||
|
||||
Reference in New Issue
Block a user