mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
use usb server for communication
This commit is contained in:
@@ -83,6 +83,24 @@ class Udc:
|
||||
u16 max_packet_size;
|
||||
u8 interval;
|
||||
} __attribute__ ((packed))
|
||||
/**/struct Device_Qualifier {
|
||||
static u8 const Type = 6;
|
||||
u8 length;
|
||||
u8 type;
|
||||
u16 version;
|
||||
u8 dev_class;
|
||||
u8 subclass;
|
||||
u8 protocol;
|
||||
u8 max_packet_size0;
|
||||
u8 num_configurations;
|
||||
u8 reserved;
|
||||
} __attribute__ ((packed))
|
||||
/**/struct Langs {
|
||||
static u8 const Type = 3;
|
||||
u8 length;
|
||||
u8 type;
|
||||
u8 lang;
|
||||
} __attribute__ ((packed))
|
||||
template <unsigned size> struct String {
|
||||
static u8 const Type = 3;
|
||||
u8 length;
|
||||
@@ -118,10 +136,12 @@ class Udc:
|
||||
Interface interface;
|
||||
Endpoint endpoint[2];
|
||||
} __attribute__ ((packed))
|
||||
static Device const device_descriptor
|
||||
static my_config const config_descriptor
|
||||
static String <7> const s_manufacturer
|
||||
static String <22> const s_product
|
||||
static Device device_descriptor
|
||||
//static Device_Qualifier device_qualifier_descriptor
|
||||
static my_config config_descriptor; //, other_config_descriptor
|
||||
static String <1> s_langs
|
||||
static String <6> s_manufacturer
|
||||
static String <16> s_product
|
||||
enum State:
|
||||
IDLE
|
||||
TX
|
||||
@@ -139,17 +159,43 @@ class Udc:
|
||||
void log (unsigned c)
|
||||
void interrupt ()
|
||||
|
||||
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 = {
|
||||
Udc::Device Udc::device_descriptor = { sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
|
||||
Udc::my_config Udc::config_descriptor = {
|
||||
(Configuration){ sizeof (Configuration), Configuration::Type, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
|
||||
(Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
|
||||
(Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
|
||||
(Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
|
||||
}
|
||||
}
|
||||
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'} }
|
||||
Udc::String <1> Udc::s_langs = { sizeof (String <1>), String <1>::Type, { 0x0409 } }
|
||||
Udc::String <6> Udc::s_manufacturer = { sizeof (String <6>), String <6>::Type, { 's', 'h', 'e', 'v', 'e', 'k' } }
|
||||
Udc::String <16> Udc::s_product = { sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
|
||||
|
||||
//Udc::Device_Qualifier const Udc::device_qualifier_descriptor = { sizeof (Device_Qualifier), Device_Qualifier::Type, 0x200, 0, 0, 0, max_packet_size0, 1, 0 }
|
||||
//Udc::my_config const Udc::other_config_descriptor = {
|
||||
// (Configuration){ sizeof (Configuration), 7, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
|
||||
// (Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
|
||||
// (Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
|
||||
// (Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
|
||||
// }
|
||||
// }
|
||||
|
||||
void Udc::init ():
|
||||
// Initialize the globals. My method of compiling doesn't do that properly.
|
||||
device_descriptor = (Device){ sizeof (Device), Device::Type, 0x200, 0, 0, 0, max_packet_size0, 0xfffe, 0x0002, 0x100, 1, 2, 0, 1 }
|
||||
config_descriptor = (my_config){
|
||||
(Configuration){ sizeof (Configuration), Configuration::Type, sizeof (my_config), 1, 1, 0, 0xc0, 1 },
|
||||
(Interface){ sizeof (Interface), Interface::Type, 0, 0, 2, 0xff, 0, 0x80, 0 }, {
|
||||
(Endpoint){ sizeof (Endpoint), Endpoint::Type, 1, BULK, max_packet_size_bulk, 0 },
|
||||
(Endpoint){ sizeof (Endpoint), Endpoint::Type, 0x81, BULK, max_packet_size_bulk, 0 }
|
||||
}
|
||||
}
|
||||
s_langs = (String <1>){ sizeof (String <1>), String <1>::Type, { 0x0409 } }
|
||||
s_manufacturer = (String <6>){ sizeof (String <6>), String <6>::Type, { 's', 'h', 'e', 'v', 'e', 'k' } }
|
||||
s_product = (String <16>){ sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
|
||||
|
||||
// Disconnect from the bus and don't try to get high-speed.
|
||||
UDC_POWER &= ~(UDC_POWER_SOFTCONN | UDC_POWER_HSENAB)
|
||||
state = IDLE
|
||||
configuration = 0
|
||||
size = 0
|
||||
@@ -164,12 +210,15 @@ void Udc::init ():
|
||||
// enable interrupts on endpoint 0.
|
||||
UDC_INTRINE |= 1 << 0
|
||||
UDC_INDEX = 0
|
||||
// Wait a bit and connect to the host.
|
||||
Kernel::my_receiver.sleep (10)
|
||||
UDC_POWER |= UDC_POWER_SOFTCONN
|
||||
|
||||
bool Udc::vendor (Setup *s):
|
||||
if s->request_type & 0x80:
|
||||
static char const *name = "abcdefgh"
|
||||
static char const *name = "Reboot"
|
||||
ptr = name
|
||||
size = 8
|
||||
size = s->length < 6 ? s->length : 6
|
||||
state = TX
|
||||
rebooting = true
|
||||
return true
|
||||
@@ -178,20 +227,34 @@ bool Udc::vendor (Setup *s):
|
||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
switch type:
|
||||
case Configuration::Type:
|
||||
if idx != 1:
|
||||
//kdebug ("config\n")
|
||||
if idx != 0:
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&config_descriptor)
|
||||
size = (len < sizeof (config_descriptor) ? len : sizeof (config_descriptor))
|
||||
break
|
||||
case Device::Type:
|
||||
//kdebug ("device\n")
|
||||
if idx != 0:
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&device_descriptor)
|
||||
size = (len < sizeof (device_descriptor) ? len : sizeof (device_descriptor))
|
||||
break
|
||||
// The 7 is an arbitrary number.
|
||||
case String <7>::Type:
|
||||
case Device_Qualifier::Type:
|
||||
//if idx != 0:
|
||||
// return false
|
||||
//ptr = reinterpret_cast <char const *> (&device_qualifier_descriptor)
|
||||
//size = (len < sizeof (device_qualifier_descriptor) ? len : sizeof (device_qualifier_descriptor))
|
||||
//break
|
||||
return false
|
||||
// The 6 is an arbitrary number, except that String <6> in instantiated already.
|
||||
case String <6>::Type:
|
||||
//kdebug ("string\n")
|
||||
switch idx:
|
||||
case 0:
|
||||
ptr = reinterpret_cast <char const *> (&s_langs)
|
||||
size = (len < sizeof (s_langs) ? len : sizeof (s_langs))
|
||||
break
|
||||
case 1:
|
||||
ptr = reinterpret_cast <char const *> (&s_manufacturer)
|
||||
size = (len < sizeof (s_manufacturer) ? len : sizeof (s_manufacturer))
|
||||
@@ -205,19 +268,21 @@ bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
break
|
||||
default:
|
||||
return false
|
||||
state = TX
|
||||
return true
|
||||
state = TX
|
||||
return true
|
||||
|
||||
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")
|
||||
//kdebug ("udc: setup: type=")
|
||||
//kdebug_num (s->request_type, 2)
|
||||
//kdebug ("; request=")
|
||||
//kdebug_num (s->request, 2)
|
||||
//kdebug ("; value=")
|
||||
//kdebug_num (s->value, 4)
|
||||
//kdebug ("; index=")
|
||||
//kdebug_num (s->index, 4)
|
||||
//kdebug ("; length=")
|
||||
//kdebug_num (s->length, 4)
|
||||
//kdebug ("\n")
|
||||
switch s->request_type:
|
||||
case STANDARD_TO_DEVICE:
|
||||
switch s->request:
|
||||
@@ -268,7 +333,7 @@ bool Udc::handle_setup (Setup *s):
|
||||
void Udc::interrupt ():
|
||||
unsigned i = UDC_INTRUSB
|
||||
if i & UDC_INTR_RESET:
|
||||
kdebug ("udc: reset\n")
|
||||
//kdebug ("udc: reset\n")
|
||||
state = IDLE
|
||||
return
|
||||
i = UDC_INTRIN
|
||||
@@ -276,7 +341,7 @@ void Udc::interrupt ():
|
||||
// Interrupt on endpoint 0.
|
||||
unsigned csr = UDC_CSR0
|
||||
if csr & UDC_CSR0_SENTSTALL:
|
||||
csr &= ~UDC_CSR0_SENTSTALL
|
||||
csr &= ~(UDC_CSR0_SENTSTALL | UDC_CSR0_SENDSTALL)
|
||||
state = IDLE
|
||||
if csr & UDC_CSR0_SETUPEND:
|
||||
csr |= UDC_CSR0_SVDSETUPEND
|
||||
@@ -292,23 +357,24 @@ void Udc::interrupt ():
|
||||
packet.d[1] = UDC_FIFO (0)
|
||||
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||
if !handle_setup (&packet.s):
|
||||
//kdebug ("stall 1\n")
|
||||
csr |= UDC_CSR0_SENDSTALL
|
||||
break
|
||||
if size == 0:
|
||||
return
|
||||
// Fall through.
|
||||
case TX:
|
||||
kdebug ("udc: send next:")
|
||||
//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)
|
||||
//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)
|
||||
//kdebug_num (*ptr, 2)
|
||||
UDC_FIFO8 (0) = *ptr++
|
||||
kdebug ("\n")
|
||||
//kdebug ("\n")
|
||||
if i == max_packet_size0:
|
||||
csr |= UDC_CSR0_INPKTRDY
|
||||
else:
|
||||
@@ -317,6 +383,7 @@ void Udc::interrupt ():
|
||||
break
|
||||
case RX:
|
||||
// Not supported.
|
||||
//kdebug ("stall 2\n")
|
||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL
|
||||
state = IDLE
|
||||
break
|
||||
@@ -340,20 +407,9 @@ Kernel::Num start ():
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
//Kernel::my_receiver.set_alarm (HZ)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case ~0:
|
||||
// alarm.
|
||||
Kernel::my_receiver.set_alarm (HZ)
|
||||
kdebug ("alarm; d =")
|
||||
unsigned mask[4] = { 0x00000000, 0xfe000000, 0x09c00000, 0x3dfc8055 }
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
kdebug (" ")
|
||||
kdebug_num (gpio_get_port (i) & mask[i])
|
||||
kdebug ("\n")
|
||||
break
|
||||
case IRQ_UDC:
|
||||
udc.interrupt ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
|
||||
Reference in New Issue
Block a user