xref: /minix/minix/lib/libhgfs/channel.c (revision 433d6423)
1 /* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
2 
3 #include "inc.h"
4 
5 #define CMD_XFER	0x1E		/* vmware backdoor transfer command */
6 
7 enum {
8   XFER_OPEN,				/* open transfer channel */
9   XFER_SENDLEN,				/* specify length of data to send */
10   XFER_SEND,				/* send data */
11   XFER_RECVLEN,				/* get length of data to receive */
12   XFER_RECV,				/* receive data */
13   XFER_RECVACK,				/* acknowledge receipt of data */
14   XFER_CLOSE				/* close transfer channel */
15 };
16 
17 #define STATUS(p) (HIWORD((p)[2]) & 0xff)
18 
19 /*===========================================================================*
20  *				channel_open				     *
21  *===========================================================================*/
channel_open(struct channel * ch,u32_t type)22 int channel_open(
23 	struct channel *ch,	/* struct describing the new channel */
24 	u32_t type         	/* channel type: CH_IN or CH_OUT */
25 )
26 {
27 /* Open a new backdoor channel. Upon success, the given channel structure will
28  * be filled with information and can be used in subsequent channel calls.
29  * Return OK on success, or a negative error code on error.
30  */
31   u32_t ptr[6];
32 
33   ptr[1] = type | 0x80000000;
34   ptr[2] = MAKELONG(CMD_XFER, XFER_OPEN);
35 
36   backdoor(ptr);
37 
38   if ((STATUS(ptr) & 1) == 0) return EIO;
39 
40   ch->id = HIWORD(ptr[3]);
41   ch->cookie1 = ptr[4];
42   ch->cookie2 = ptr[5];
43 
44   return OK;
45 }
46 
47 /*===========================================================================*
48  *				channel_close				     *
49  *===========================================================================*/
channel_close(struct channel * ch)50 void channel_close(
51 	struct channel *ch	/* backdoor channel to close */
52 )
53 {
54 /* Close a previously opened backdoor channel.
55  */
56   u32_t ptr[6];
57 
58   ptr[2] = MAKELONG(CMD_XFER, XFER_CLOSE);
59   ptr[3] = MAKELONG(0, ch->id);
60   ptr[4] = ch->cookie1;
61   ptr[5] = ch->cookie2;
62 
63   backdoor(ptr);
64 }
65 
66 /*===========================================================================*
67  *				channel_send				     *
68  *===========================================================================*/
channel_send(struct channel * ch,char * buf,int len)69 int channel_send(
70 	struct channel *ch,	/* backdoor channel to send to */
71 	char *buf,         	/* buffer to send data from */
72 	int len            	/* size of the data to send */
73 )
74 {
75 /* Receive data over a backdoor channel. Return OK on success, or a negative
76  * error code on error.
77  */
78   u32_t ptr[7];
79 
80   ptr[1] = len;
81   ptr[2] = MAKELONG(CMD_XFER, XFER_SENDLEN);
82   ptr[3] = MAKELONG(0, ch->id);
83   ptr[4] = ch->cookie1;
84   ptr[5] = ch->cookie2;
85 
86   backdoor(ptr);
87 
88   if ((STATUS(ptr) & 1) == 0) return EIO;
89 
90   if (len == 0) return OK;
91 
92   ptr[1] = MAKELONG(0, 1);
93   ptr[2] = len;
94   ptr[3] = MAKELONG(0, ch->id);
95   ptr[4] = (u32_t)buf;
96   ptr[5] = ch->cookie2;
97   ptr[6] = ch->cookie1;
98 
99   backdoor_out(ptr);
100 
101   return OK;
102 }
103 
104 /*===========================================================================*
105  *				channel_recv				     *
106  *===========================================================================*/
channel_recv(struct channel * ch,char * buf,int max)107 int channel_recv(
108 	struct channel *ch,	/* backdoor channel to receive from */
109 	char *buf,         	/* buffer to receive data into */
110 	int max            	/* size of the buffer */
111 )
112 {
113 /* Receive data on a backdoor channel. Return the number of bytes received, or
114  * a negative error code on error.
115  */
116   u32_t ptr[7];
117   int len;
118 
119   ptr[2] = MAKELONG(CMD_XFER, XFER_RECVLEN);
120   ptr[3] = MAKELONG(0, ch->id);
121   ptr[4] = ch->cookie1;
122   ptr[5] = ch->cookie2;
123 
124   backdoor(ptr);
125 
126   if ((STATUS(ptr) & 0x81) == 0) return EIO;
127 
128   if ((len = ptr[1]) == 0 || (STATUS(ptr) & 3) == 1) return 0;
129 
130   if (len > max) return E2BIG;
131 
132   ptr[1] = MAKELONG(0, 1);
133   ptr[2] = len;
134   ptr[3] = MAKELONG(0, ch->id);
135   ptr[4] = ch->cookie1;
136   ptr[5] = (u32_t)buf;
137   ptr[6] = ch->cookie2;
138 
139   backdoor_in(ptr);
140 
141   ptr[1] = 1;
142   ptr[2] = MAKELONG(CMD_XFER, XFER_RECVACK);
143   ptr[3] = MAKELONG(0, ch->id);
144   ptr[4] = ch->cookie1;
145   ptr[5] = ch->cookie2;
146 
147   backdoor(ptr);
148 
149   return len;
150 }
151