18#define READ_ONCE(x)       (*(const volatile typeof(x) *)(&x)) 
   19#define WRITE_ONCE(x, val) (*(volatile typeof(x) *)(&x) = (val)) 
   73    return READ_ONCE(q->read) == READ_ONCE(q->write);
 
   76static void QueuePush(
struct tty_queue *q, 
char c)
 
   78    int w = READ_ONCE(q->write);
 
   81    WRITE_ONCE(q->write, w + 1);
 
   86    int r = READ_ONCE(q->read);
 
   89    ret = q->buf[r & 0xff];
 
   90    WRITE_ONCE(q->read, r + 1);
 
   95void sceTtyHandler(
int event, 
int param, 
void *opt)
 
  103        case DECI2_READ_DONE:
 
  111            if (pkt->length > offsetof(
struct tty_packet, buf)) {
 
  112                for (
int i = 0; i < pkt->length - offsetof(
struct tty_packet, buf); i++) {
 
  113                    QueuePush(
tinfo->read_queue, pkt->buf[i]);
 
  129        case DECI2_WRITE_DONE:
 
  135int sceTtyWrite(
char *buf, 
int len)
 
  138    int oldintr, ret, ssize;
 
  148    tinfo.wptr    = UNCACHED_SEG(&wbuf);
 
  149    pkt           = UNCACHED_SEG(&wbuf);
 
  153    for (ret = 0; ret < len; ret++) {
 
  168    pkt->length = 
tinfo.wlen;
 
  169    if (sceDeci2ReqSend(
tinfo.socket, pkt->destination) < 0) {
 
  178    while (READ_ONCE(
tinfo.writing)) {
 
  179        sceDeci2Poll(
tinfo.socket);
 
  190int sceTtyRead(
char *buf, 
int len)
 
  194    for (i = 0; i < len; i++) {
 
  195        while (QueueEmpty(
tinfo.read_queue))
 
  198        buf[i] = QueuePop(
tinfo.read_queue);
 
  199        if (buf[i] == 
'\n' || buf[i] == 
'\r') {
 
  212    tinfo.socket = sceDeci2Open(0x210, &
tinfo, sceTtyHandler);
 
  213    if (
tinfo.socket < 0) {
 
  219    tinfo.rptr    = UNCACHED_SEG(&rbuf);
 
  220    tinfo.wptr    = UNCACHED_SEG(&wbuf);
 
  222    pkt              = UNCACHED_SEG(&wbuf);
 
  223    pkt->protocol    = 0x210;
 
  225    pkt->destination = 
'H';
 
  228    pkt->ttyp_reserved = 0;
 
  230    tinfo.read_queue = QueueInit();