1 /*********************************************************************
2 * Copyright (C) 2003 Tord Lindstrom (pukko@home.se)
3 * Copyright (C) 2004 adresd (adresd_ps2dev@yahoo.com)
4 * This file is subject to the terms and conditions of the PS2Link License.
5 * See the file LICENSE in the main directory of this distribution for more
9 // Fu*k knows why net_fio & net_fsys are separated..
17 #include <io_common.h>
23 #define ntohl(x) htonl(x)
24 #define ntohs(x) htons(x)
26 unsigned int remote_pc_addr
= 0xffffffff;
28 #define PACKET_MAXSIZE 4096
30 static char send_packet
[PACKET_MAXSIZE
] __attribute__((aligned(16)));
31 static char recv_packet
[PACKET_MAXSIZE
] __attribute__((aligned(16)));
33 static int pko_fileio_sock
= -1;
34 static int pko_fileio_active
= 0;
37 #define dbgprintf(args...) printf(args)
39 #define dbgprintf(args...) do { } while(0)
42 //----------------------------------------------------------------------
45 pko_close_socket(void)
49 ret
= disconnect(pko_fileio_sock
);
51 printf("pko_file: disconnect returned error %d\n", ret
);
56 //----------------------------------------------------------------------
61 if (pko_fileio_sock
> 0) {
62 disconnect(pko_fileio_sock
);
64 pko_fileio_active
= 0;
68 //----------------------------------------------------------------------
69 // XXX: Hm, this func should behave sorta like pko_recv_bytes imho..
70 // i.e. check if it was able to send just a part of the packet etc..
72 pko_lwip_send(int sock
, void *buf
, int len
, int flag
)
75 ret
= send(sock
, buf
, len
, flag
);
77 dbgprintf("pko_file: lwip_send() error %d\n", ret
);
87 //----------------------------------------------------------------------
88 // Do repetetive recv() calles until 'bytes' bytes are received
90 int pko_recv_bytes(int sock
, char *buf
, int bytes
)
98 len
= recv(sock
, &buf
[bytes
- left
], left
, 0);
100 dbgprintf("pko_file: pko_recv_bytes error!!\n");
109 //----------------------------------------------------------------------
110 // Receive a 'packet' of the expected type 'pkt_type', and lenght 'len'
111 int pko_accept_pkt(int sock
, char *buf
, int len
, int pkt_type
)
119 length
= pko_recv_bytes(sock
, buf
, sizeof(pko_pkt_hdr
));
121 dbgprintf("pko_file: accept_pkt recv error\n");
125 if (length
< sizeof(pko_pkt_hdr
)) {
126 dbgprintf("pko_file: XXX: did not receive a full header!!!! "
127 "Fix this! (%d)\n", length
);
130 hdr
= (pko_pkt_hdr
*)buf
;
131 hcmd
= ntohl(hdr
->cmd
);
132 hlen
= ntohs(hdr
->len
);
134 if (hcmd
!= pkt_type
) {
135 dbgprintf("pko_file: pko_accept_pkt: Expected %x, got %x\n",
141 dbgprintf("pko_file: pko_accept_pkt: hdr->len is too large!! "
142 "(%d, can only receive %d)\n", hlen
, len
);
146 // get the actual packet data
147 length
= pko_recv_bytes(sock
, buf
+ sizeof(pko_pkt_hdr
),
148 hlen
- sizeof(pko_pkt_hdr
));
151 dbgprintf("pko_file: accept recv2 error!!\n");
155 if (length
< (hlen
- sizeof(pko_pkt_hdr
))) {
156 dbgprintf("pko_accept_pkt: Did not receive full packet!!! "
157 "Fix this! (%d)\n", length
);
163 //----------------------------------------------------------------------
165 int pko_open_file(char *path
, int flags
)
167 pko_pkt_open_req
*openreq
;
168 pko_pkt_file_rly
*openrly
;
170 if (pko_fileio_sock
< 0) {
174 dbgprintf("pko_file: file open req (%s, %x)\n", path
, flags
);
176 openreq
= (pko_pkt_open_req
*)&send_packet
[0];
179 openreq
->cmd
= htonl(PKO_OPEN_CMD
);
180 openreq
->len
= htons((unsigned short)sizeof(pko_pkt_open_req
));
181 openreq
->flags
= htonl(flags
);
182 strncpy(openreq
->path
, path
, PKO_MAX_PATH
);
183 openreq
->path
[PKO_MAX_PATH
- 1] = 0; // Make sure it's null-terminated
185 if (pko_lwip_send(pko_fileio_sock
, openreq
, sizeof(pko_pkt_open_req
), 0) < 0) {
189 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
190 sizeof(pko_pkt_file_rly
), PKO_OPEN_RLY
)) {
191 dbgprintf("pko_file: pko_open_file: did not receive OPEN_RLY\n");
195 openrly
= (pko_pkt_file_rly
*)recv_packet
;
197 dbgprintf("pko_file: file open reply received (ret %d)\n", ntohl(openrly
->retval
));
199 return ntohl(openrly
->retval
);
203 //----------------------------------------------------------------------
205 int pko_close_file(int fd
)
207 pko_pkt_close_req
*closereq
;
208 pko_pkt_file_rly
*closerly
;
211 if (pko_fileio_sock
< 0) {
215 dbgprintf("pko_file: file close req (fd: %d)\n", fd
);
217 closereq
= (pko_pkt_close_req
*)&send_packet
[0];
218 closerly
= (pko_pkt_file_rly
*)&recv_packet
[0];
220 closereq
->cmd
= htonl(PKO_CLOSE_CMD
);
221 closereq
->len
= htons((unsigned short)sizeof(pko_pkt_close_req
));
222 closereq
->fd
= htonl(fd
);
224 if (pko_lwip_send(pko_fileio_sock
, closereq
, sizeof(pko_pkt_close_req
), 0) < 0) {
228 if(!pko_accept_pkt(pko_fileio_sock
, (char *)closerly
,
229 sizeof(pko_pkt_file_rly
), PKO_CLOSE_RLY
)) {
230 dbgprintf("pko_file: pko_close_file: did not receive PKO_CLOSE_RLY\n");
234 dbgprintf("pko_file: pko_close_file: close reply received (ret %d)\n",
235 ntohl(closerly
->retval
));
237 return ntohl(closerly
->retval
);
240 //----------------------------------------------------------------------
242 int pko_lseek_file(int fd
, unsigned int offset
, int whence
)
244 pko_pkt_lseek_req
*lseekreq
;
245 pko_pkt_file_rly
*lseekrly
;
248 if (pko_fileio_sock
< 0) {
252 dbgprintf("pko_file: file lseek req (fd: %d)\n", fd
);
254 lseekreq
= (pko_pkt_lseek_req
*)&send_packet
[0];
255 lseekrly
= (pko_pkt_file_rly
*)&recv_packet
[0];
257 lseekreq
->cmd
= htonl(PKO_LSEEK_CMD
);
258 lseekreq
->len
= htons((unsigned short)sizeof(pko_pkt_lseek_req
));
259 lseekreq
->fd
= htonl(fd
);
260 lseekreq
->offset
= htonl(offset
);
261 lseekreq
->whence
= htonl(whence
);
263 if(pko_lwip_send(pko_fileio_sock
, lseekreq
, sizeof(pko_pkt_lseek_req
), 0) < 0) {
267 if(!pko_accept_pkt(pko_fileio_sock
, (char *)lseekrly
,
268 sizeof(pko_pkt_file_rly
), PKO_LSEEK_RLY
)) {
269 dbgprintf("pko_file: pko_lseek_file: did not receive PKO_LSEEK_RLY\n");
273 dbgprintf("pko_file: pko_lseek_file: lseek reply received (ret %d)\n",
274 ntohl(lseekrly
->retval
));
276 return ntohl(lseekrly
->retval
);
281 //----------------------------------------------------------------------
283 int pko_write_file(int fd
, char *buf
, int length
)
285 pko_pkt_write_req
*writecmd
;
286 pko_pkt_file_rly
*writerly
;
292 if (pko_fileio_sock
< 0) {
296 dbgprintf("pko_file: file write req (fd: %d)\n", fd
);
298 writecmd
= (pko_pkt_write_req
*)&send_packet
[0];
299 writerly
= (pko_pkt_file_rly
*)&recv_packet
[0];
301 hlen
= (unsigned short)sizeof(pko_pkt_write_req
);
302 writecmd
->cmd
= htonl(PKO_WRITE_CMD
);
303 writecmd
->len
= htons(hlen
);
304 writecmd
->fd
= htonl(fd
);
306 // Divide the write request
308 while (writtenbytes
< length
) {
310 if ((length
- writtenbytes
) > PKO_MAX_WRITE_SEGMENT
) {
311 // Need to split in several read reqs
312 nbytes
= PKO_MAX_READ_SEGMENT
;
315 nbytes
= length
- writtenbytes
;
318 writecmd
->nbytes
= htonl(nbytes
);
320 /* Send the packet header. */
321 if (pko_lwip_send(pko_fileio_sock
, writecmd
, hlen
, 0) < 0)
323 /* Send the write() data. */
324 if (pko_lwip_send(pko_fileio_sock
, &buf
[writtenbytes
], nbytes
, 0) < 0)
327 // Copy data to the acutal packet
328 memcpy(&send_packet
[sizeof(pko_pkt_write_req
)], &buf
[writtenbytes
],
331 if (pko_lwip_send(pko_fileio_sock
, writecmd
, hlen
+ nbytes
, 0) < 0)
337 if(!pko_accept_pkt(pko_fileio_sock
, (char *)writerly
,
338 sizeof(pko_pkt_file_rly
), PKO_WRITE_RLY
)) {
339 dbgprintf("pko_file: pko_write_file: "
340 "did not receive PKO_WRITE_RLY\n");
343 retval
= ntohl(writerly
->retval
);
345 dbgprintf("pko_file: wrote %d bytes (asked for %d)\n",
350 dbgprintf("pko_file: pko_write_file: received error on write req (%d)\n",
355 writtenbytes
+= retval
;
356 if (retval
< nbytes
) {
364 //----------------------------------------------------------------------
366 int pko_read_file(int fd
, char *buf
, int length
)
371 pko_pkt_read_req
*readcmd
;
372 pko_pkt_read_rly
*readrly
;
375 if (pko_fileio_sock
< 0) {
379 readcmd
= (pko_pkt_read_req
*)&send_packet
[0];
380 readrly
= (pko_pkt_read_rly
*)&recv_packet
[0];
383 readcmd
->cmd
= htonl(PKO_READ_CMD
);
384 readcmd
->len
= htons((unsigned short)sizeof(pko_pkt_read_req
));
385 readcmd
->fd
= htonl(fd
);
390 dbgprintf("pko_read_file: illegal req!! (whish to read < 0 bytes!)\n");
394 readcmd
->nbytes
= htonl(length
);
396 i
= send(pko_fileio_sock
, readcmd
, sizeof(pko_pkt_read_req
), 0);
399 dbgprintf("pko_file: pko_read_file: send failed (%d)\n", i
);
403 if(!pko_accept_pkt(pko_fileio_sock
, (char *)readrly
,
404 sizeof(pko_pkt_read_rly
), PKO_READ_RLY
)) {
405 dbgprintf("pko_file: pko_read_file: "
406 "did not receive PKO_READ_RLY\n");
410 nbytes
= ntohl(readrly
->nbytes
);
411 dbgprintf("pko_file: pko_read_file: Reply said there's %d bytes to read "
412 "(wanted %d)\n", nbytes
, length
);
414 // Now read the actual file data
415 i
= pko_recv_bytes(pko_fileio_sock
, &buf
[0], nbytes
);
417 dbgprintf("pko_file: pko_read_file, data read error\n");
424 //----------------------------------------------------------------------
426 int pko_remove(char *name
)
428 pko_pkt_remove_req
*removereq
;
429 pko_pkt_file_rly
*removerly
;
431 if (pko_fileio_sock
< 0) {
435 dbgprintf("pko_file: file remove req (%s)\n", name
);
437 removereq
= (pko_pkt_remove_req
*)&send_packet
[0];
440 removereq
->cmd
= htonl(PKO_REMOVE_CMD
);
441 removereq
->len
= htons((unsigned short)sizeof(pko_pkt_remove_req
));
442 strncpy(removereq
->name
, name
, PKO_MAX_PATH
);
443 removereq
->name
[PKO_MAX_PATH
- 1] = 0; // Make sure it's null-terminated
445 if (pko_lwip_send(pko_fileio_sock
, removereq
, sizeof(pko_pkt_remove_req
), 0) < 0) {
449 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
450 sizeof(pko_pkt_file_rly
), PKO_REMOVE_RLY
)) {
451 dbgprintf("pko_file: pko_remove: did not receive REMOVE_RLY\n");
455 removerly
= (pko_pkt_file_rly
*)recv_packet
;
456 dbgprintf("pko_file: file remove reply received (ret %d)\n", ntohl(removerly
->retval
));
457 return ntohl(removerly
->retval
);
460 //----------------------------------------------------------------------
462 int pko_mkdir(char *name
, int mode
)
464 pko_pkt_mkdir_req
*mkdirreq
;
465 pko_pkt_file_rly
*mkdirrly
;
467 if (pko_fileio_sock
< 0) {
471 dbgprintf("pko_file: make dir req (%s)\n", name
);
473 mkdirreq
= (pko_pkt_mkdir_req
*)&send_packet
[0];
476 mkdirreq
->cmd
= htonl(PKO_MKDIR_CMD
);
477 mkdirreq
->len
= htons((unsigned short)sizeof(pko_pkt_mkdir_req
));
478 mkdirreq
->mode
= mode
;
479 strncpy(mkdirreq
->name
, name
, PKO_MAX_PATH
);
480 mkdirreq
->name
[PKO_MAX_PATH
- 1] = 0; // Make sure it's null-terminated
482 if (pko_lwip_send(pko_fileio_sock
, mkdirreq
, sizeof(pko_pkt_mkdir_req
), 0) < 0) {
486 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
487 sizeof(pko_pkt_file_rly
), PKO_MKDIR_RLY
)) {
488 dbgprintf("pko_file: pko_mkdir: did not receive MKDIR_RLY\n");
492 mkdirrly
= (pko_pkt_file_rly
*)recv_packet
;
493 dbgprintf("pko_file: make dir reply received (ret %d)\n", ntohl(mkdirrly
->retval
));
494 return ntohl(mkdirrly
->retval
);
497 //----------------------------------------------------------------------
499 int pko_rmdir(char *name
)
501 pko_pkt_rmdir_req
*rmdirreq
;
502 pko_pkt_file_rly
*rmdirrly
;
504 if (pko_fileio_sock
< 0) {
508 dbgprintf("pko_file: remove dir req (%s)\n", name
);
510 rmdirreq
= (pko_pkt_rmdir_req
*)&send_packet
[0];
513 rmdirreq
->cmd
= htonl(PKO_RMDIR_CMD
);
514 rmdirreq
->len
= htons((unsigned short)sizeof(pko_pkt_rmdir_req
));
515 strncpy(rmdirreq
->name
, name
, PKO_MAX_PATH
);
516 rmdirreq
->name
[PKO_MAX_PATH
- 1] = 0; // Make sure it's null-terminated
518 if (pko_lwip_send(pko_fileio_sock
, rmdirreq
, sizeof(pko_pkt_rmdir_req
), 0) < 0) {
522 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
523 sizeof(pko_pkt_file_rly
), PKO_RMDIR_RLY
)) {
524 dbgprintf("pko_file: pko_rmdir: did not receive RMDIR_RLY\n");
528 rmdirrly
= (pko_pkt_file_rly
*)recv_packet
;
529 dbgprintf("pko_file: remove dir reply received (ret %d)\n", ntohl(rmdirrly
->retval
));
530 return ntohl(rmdirrly
->retval
);
533 //----------------------------------------------------------------------
535 int pko_open_dir(char *path
)
537 pko_pkt_open_req
*openreq
;
538 pko_pkt_file_rly
*openrly
;
540 if (pko_fileio_sock
< 0) {
544 dbgprintf("pko_file: dir open req (%s)\n", path
);
546 openreq
= (pko_pkt_open_req
*)&send_packet
[0];
549 openreq
->cmd
= htonl(PKO_OPENDIR_CMD
);
550 openreq
->len
= htons((unsigned short)sizeof(pko_pkt_open_req
));
551 openreq
->flags
= htonl(0);
552 strncpy(openreq
->path
, path
, PKO_MAX_PATH
);
553 openreq
->path
[PKO_MAX_PATH
- 1] = 0; // Make sure it's null-terminated
555 if (pko_lwip_send(pko_fileio_sock
, openreq
, sizeof(pko_pkt_open_req
), 0) < 0) {
559 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
560 sizeof(pko_pkt_file_rly
), PKO_OPENDIR_RLY
)) {
561 dbgprintf("pko_file: pko_open_dir: did not receive OPENDIR_RLY\n");
565 openrly
= (pko_pkt_file_rly
*)recv_packet
;
567 dbgprintf("pko_file: dir open reply received (ret %d)\n", ntohl(openrly
->retval
));
569 return ntohl(openrly
->retval
);
572 //----------------------------------------------------------------------
574 int pko_read_dir(int fd
, void *buf
)
576 pko_pkt_dread_req
*dirreq
;
577 pko_pkt_dread_rly
*dirrly
;
578 fio_dirent_t
*dirent
;
580 if (pko_fileio_sock
< 0) {
584 dbgprintf("pko_file: dir read req (%x)\n", fd
);
586 dirreq
= (pko_pkt_dread_req
*)&send_packet
[0];
589 dirreq
->cmd
= htonl(PKO_READDIR_CMD
);
590 dirreq
->len
= htons((unsigned short)sizeof(pko_pkt_dread_req
));
591 dirreq
->fd
= htonl(fd
);
593 if (pko_lwip_send(pko_fileio_sock
, dirreq
, sizeof(pko_pkt_dread_req
), 0) < 0) {
597 if (!pko_accept_pkt(pko_fileio_sock
, recv_packet
,
598 sizeof(pko_pkt_dread_rly
), PKO_READDIR_RLY
)) {
599 dbgprintf("pko_file: pko_read_dir: did not receive OPENDIR_RLY\n");
603 dirrly
= (pko_pkt_dread_rly
*)recv_packet
;
605 dbgprintf("pko_file: dir read reply received (ret %d)\n", ntohl(dirrly
->retval
));
607 dirent
= (fio_dirent_t
*) buf
;
608 // now handle the return buffer translation, to build reply bit
609 dirent
->stat
.mode
= ntohl(dirrly
->mode
);
610 dirent
->stat
.attr
= ntohl(dirrly
->attr
);
611 dirent
->stat
.size
= ntohl(dirrly
->size
);
612 dirent
->stat
.hisize
= ntohl(dirrly
->hisize
);
613 memcpy(dirent
->stat
.ctime
,dirrly
->ctime
,8*3);
614 strncpy(dirent
->name
,dirrly
->name
,256);
617 return ntohl(dirrly
->retval
);
621 //----------------------------------------------------------------------
623 int pko_close_dir(int fd
)
625 pko_pkt_close_req
*closereq
;
626 pko_pkt_file_rly
*closerly
;
629 if (pko_fileio_sock
< 0) {
633 dbgprintf("pko_file: dir close req (fd: %d)\n", fd
);
635 closereq
= (pko_pkt_close_req
*)&send_packet
[0];
636 closerly
= (pko_pkt_file_rly
*)&recv_packet
[0];
638 closereq
->cmd
= htonl(PKO_CLOSEDIR_CMD
);
639 closereq
->len
= htons((unsigned short)sizeof(pko_pkt_close_req
));
640 closereq
->fd
= htonl(fd
);
642 if (pko_lwip_send(pko_fileio_sock
, closereq
, sizeof(pko_pkt_close_req
), 0) < 0) {
646 if(!pko_accept_pkt(pko_fileio_sock
, (char *)closerly
,
647 sizeof(pko_pkt_file_rly
), PKO_CLOSEDIR_RLY
)) {
648 dbgprintf("pko_file: pko_close_dir: did not receive PKO_CLOSEDIR_RLY\n");
652 dbgprintf("pko_file: dir close reply received (ret %d)\n",
653 ntohl(closerly
->retval
));
655 return ntohl(closerly
->retval
);
658 //----------------------------------------------------------------------
659 // Thread that waits for a PC to connect/disconnect/reconnect blah..
661 pko_file_serv(void *argv
)
663 struct sockaddr_in server_addr
;
664 struct sockaddr_in client_addr
;
670 dbgprintf(" - PS2 Side application -\n");
672 memset((void *)&server_addr
, 0, sizeof(server_addr
));
673 // Should perhaps specify PC side ip..
674 server_addr
.sin_family
= AF_INET
;
675 server_addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
676 server_addr
.sin_port
= htons(PKO_PORT
);
678 while ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
679 dbgprintf("pko_file: socket creation error (%d)\n", sock
);
683 ret
= bind(sock
, (struct sockaddr
*)&server_addr
,
684 sizeof(server_addr
));
686 dbgprintf("pko_file: bind error (%d)\n", ret
);
691 ret
= listen(sock
, 5);
694 dbgprintf("pko_file: listen error (%d)\n", ret
);
699 // Active flag kinda sux, cause it wont be checked until a new client has
700 // connected.. But it's better than nothing and good for now at least
701 pko_fileio_active
= 1;
704 while(pko_fileio_active
)
706 dbgprintf("Waiting for connection\n");
708 client_len
= sizeof(client_addr
);
709 client_sock
= accept(sock
, (struct sockaddr
*)&client_addr
,
711 if (client_sock
< 0) {
712 dbgprintf("pko_file: accept error (%d)", client_sock
);
716 dbgprintf("Client connected from %x\n",
717 (int)client_addr
.sin_addr
.s_addr
);
719 remote_pc_addr
= client_addr
.sin_addr
.s_addr
;
721 if (pko_fileio_sock
> 0) {
722 dbgprintf("Client reconnected\n");
723 ret
= disconnect(pko_fileio_sock
);
724 dbgprintf("close ret %d\n", ret
);
726 pko_fileio_sock
= client_sock
;
729 if (pko_fileio_sock
> 0) {
730 disconnect(pko_fileio_sock
);