| #include "contiki.h" |
| #include "psock.h" |
| #include "ctk-draw.h" |
| |
| #include <cbm.h> |
| #include <c64.h> |
| #include <string.h> |
| |
| static struct { |
| struct psock sout, sin; |
| struct pt inpt, outpt; |
| char outputbuf[200]; |
| char inputbuf[200]; |
| unsigned short len; |
| } s; |
| |
| #define CURSOR_ON() *(char *)0xcc = 0 |
| #define CURSOR_OFF() *(char *)0xcc = 1 |
| static void ctkmode(void); |
| /*---------------------------------------------------------------------------*/ |
| static |
| PT_THREAD(send(void)) |
| { |
| PSOCK_BEGIN(&s.sout); |
| |
| PSOCK_SEND(&s.sout, s.outputbuf, s.len); |
| PSOCK_END(&s.sout); |
| } |
| /*---------------------------------------------------------------------------*/ |
| static |
| PT_THREAD(handle_output(void)) |
| { |
| ctk_arch_key_t c; |
| char *ptr; |
| |
| PT_BEGIN(&s.outpt); |
| |
| while(1) { |
| PT_WAIT_UNTIL(&s.outpt, (ctk_mode_get() == CTK_MODE_EXTERNAL) && |
| kbhit()); |
| |
| |
| ptr = s.outputbuf; |
| s.len = 0; |
| while(kbhit() && s.len < sizeof(s.outputbuf)) { |
| c = cgetc(); |
| *ptr = c; |
| ++ptr; |
| ++s.len; |
| } |
| |
| PT_WAIT_THREAD(&s.outpt, send()); |
| } |
| PT_END(&s.outpt); |
| } |
| /*---------------------------------------------------------------------------*/ |
| static |
| PT_THREAD(handle_input(void)) |
| { |
| unsigned short i; |
| char *ptr; |
| char next; |
| |
| next = 1; |
| PT_BEGIN(&s.inpt); |
| |
| while(1) { |
| /* Wait until data arrives. */ |
| next = 0; |
| PT_WAIT_UNTIL(&s.inpt, next && uip_newdata()); |
| |
| CURSOR_OFF(); |
| /* Print it out on the screen. */ |
| ptr = (char *)uip_appdata; |
| for(i = 0; i < uip_len; ++i) { |
| cbm_k_bsout(*ptr); |
| ++ptr; |
| } |
| CURSOR_ON(); |
| } |
| PT_END(&s.inpt); |
| } |
| /*---------------------------------------------------------------------------*/ |
| static void |
| appcall(void *state) |
| { |
| if(uip_closed() || uip_aborted() || uip_timedout()) { |
| ctkmode(); |
| } else if(uip_connected()) { |
| } else { |
| handle_input(); |
| handle_output(); |
| } |
| } |
| /*---------------------------------------------------------------------------*/ |
| static struct uip_conn * |
| connect(u16_t *host, u16_t port) |
| { |
| PSOCK_INIT(&s.sin, s.inputbuf, sizeof(s.inputbuf)); |
| PSOCK_INIT(&s.sout, s.inputbuf, sizeof(s.inputbuf)); |
| PT_INIT(&s.inpt); |
| PT_INIT(&s.outpt); |
| return tcp_connect(host, htons(port), NULL); |
| } |
| /*---------------------------------------------------------------------------*/ |
| EK_POLLHANDLER(pollhandler); |
| EK_EVENTHANDLER(eventhandler, ev, data); |
| EK_PROCESS(p, "C/G terminal", EK_PRIO_NORMAL, |
| eventhandler, pollhandler, NULL); |
| static ek_id_t id = EK_ID_NONE; |
| static struct uip_conn *conn; |
| static u16_t serveraddr[2]; |
| static u16_t serverport; |
| /*---------------------------------------------------------------------------*/ |
| static struct ctk_window window; |
| static struct ctk_label hostlabel = |
| {CTK_LABEL(0, 0, 4, 1, "Host")}; |
| static char host[32]; |
| static struct ctk_textentry hostentry = |
| {CTK_TEXTENTRY(5, 0, 20, 1, host, sizeof(host) - 1)}; |
| static struct ctk_label portlabel = |
| {CTK_LABEL(27, 0, 4, 1, "Port")}; |
| static char port[7]; |
| static struct ctk_textentry portentry = |
| {CTK_TEXTENTRY(32, 0, 4, 1, port, sizeof(port) - 1)}; |
| static struct ctk_button connectbutton = |
| {CTK_BUTTON(0, 2, 7, "Connect")}; |
| static struct ctk_button switchbutton = |
| {CTK_BUTTON(30, 2, 6, "Switch")}; |
| static struct ctk_label helplabel = |
| {CTK_LABEL(0, 4, 37, 1, "RUN/STOP to return from terminal view")}; |
| /*---------------------------------------------------------------------------*/ |
| LOADER_INIT_FUNC(cgterm_init, arg) |
| { |
| arg_free(arg); |
| if(id == EK_ID_NONE) { |
| id = ek_start(&p); |
| } |
| } |
| /*---------------------------------------------------------------------------*/ |
| static void |
| ctkmode(void) |
| { |
| ctk_mode_set(CTK_MODE_NORMAL); |
| ctk_draw_init(); |
| ctk_desktop_redraw(NULL); |
| } |
| /*---------------------------------------------------------------------------*/ |
| static void |
| textmode(void) |
| { |
| ctk_mode_set(CTK_MODE_EXTERNAL); |
| |
| VIC.ctrl1 = 0x1b; /* $D011 */ |
| VIC.addr = 0x17; /* $D018 */ |
| VIC.ctrl2 = 0xc8; /* $D016 */ |
| CIA2.pra = 0x03; /* $DD00 */ |
| |
| VIC.bordercolor = 0x00; /* $D020 */ |
| VIC.bgcolor0 = 0x00; /* $D021 */ |
| |
| CURSOR_ON(); |
| } |
| /*---------------------------------------------------------------------------*/ |
| EK_EVENTHANDLER(eventhandler, ev, data) |
| { |
| u16_t *ipaddr; |
| char *cptr; |
| |
| if(ev == tcpip_event) { |
| appcall(data); |
| } else if(ev == EK_EVENT_INIT) { |
| ctk_window_new(&window, 38, 5, "C/G term"); |
| CTK_WIDGET_ADD(&window, &hostlabel); |
| CTK_WIDGET_ADD(&window, &hostentry); |
| CTK_WIDGET_ADD(&window, &portlabel); |
| CTK_WIDGET_ADD(&window, &portentry); |
| CTK_WIDGET_ADD(&window, &connectbutton); |
| CTK_WIDGET_ADD(&window, &switchbutton); |
| CTK_WIDGET_ADD(&window, &helplabel); |
| ctk_window_open(&window); |
| } else if(ev == ctk_signal_widget_activate) { |
| |
| if(data == (ek_data_t)&switchbutton) { |
| textmode(); |
| } else if(data == (ek_data_t)&connectbutton) { |
| serverport = 0; |
| for(cptr = port; *cptr != ' ' && *cptr != 0; ++cptr) { |
| if(*cptr < '0' || *cptr > '9') { |
| return; |
| } |
| serverport = 10 * serverport + *cptr - '0'; |
| } |
| |
| ipaddr = serveraddr; |
| if(uiplib_ipaddrconv(host, (u8_t *)serveraddr) == 0) { |
| ipaddr = resolv_lookup(host); |
| if(ipaddr == NULL) { |
| resolv_query(host); |
| } else { |
| uip_ipaddr_copy(serveraddr, ipaddr); |
| } |
| } |
| if(ipaddr != NULL) { |
| conn = connect(serveraddr, serverport); |
| if(conn != NULL) { |
| memset((char *)0x0400, 0x20, 40*25); |
| memset((char *)0xd800, 0x01, 40*25); |
| textmode(); |
| } |
| } |
| } |
| } else if(ev == resolv_event_found) { |
| ipaddr = resolv_lookup(host); |
| if(ipaddr != NULL) { |
| uip_ipaddr_copy(serveraddr, ipaddr); |
| |
| conn = connect(serveraddr, serverport); |
| if(conn != NULL) { |
| memset((char *)0x0400, 0x20, 40*25); |
| memset((char *)0xd800, 0x01, 40*25); |
| textmode(); |
| } |
| } |
| } else if(ev == EK_EVENT_REQUEST_EXIT || |
| ev == ctk_signal_window_close) { |
| ctk_window_close(&window); |
| ek_exit(); |
| LOADER_UNLOAD(); |
| } |
| } |
| /*---------------------------------------------------------------------------*/ |
| EK_POLLHANDLER(pollhandler) |
| { |
| if(ctk_mode_get() == CTK_MODE_EXTERNAL) { |
| if(CIA1.prb == 0x7f) { |
| ctkmode(); |
| } else if(kbhit() && conn != NULL) { |
| tcpip_poll_tcp(conn); |
| } |
| } |
| } |
| /*---------------------------------------------------------------------------*/ |