xref: /minix3/minix/lib/libc/sys/ioctl.c (revision ed223591a80825b9ab0fea00740579140b6d2a8e)
1433d6423SLionel Sambuc #include <sys/cdefs.h>
2433d6423SLionel Sambuc #include "namespace.h"
3433d6423SLionel Sambuc #include <lib.h>
4433d6423SLionel Sambuc #include <stdarg.h>
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc #include <sys/ioctl.h>
7433d6423SLionel Sambuc #include <minix/i2c.h>
8433d6423SLionel Sambuc #include <string.h>
9433d6423SLionel Sambuc #include <sys/ioccom.h>
10433d6423SLionel Sambuc #include <stdarg.h>
11*ed223591SDavid van Moolenbroek #include <fcntl.h>
12433d6423SLionel Sambuc 
13433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out,
14433d6423SLionel Sambuc     i2c_ioctl_exec_t *in);
15433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out,
16433d6423SLionel Sambuc     minix_i2c_ioctl_exec_t *in);
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out,
19433d6423SLionel Sambuc 	i2c_ioctl_exec_t *in)
20433d6423SLionel Sambuc {
21433d6423SLionel Sambuc   memset(out, '\0', sizeof(minix_i2c_ioctl_exec_t));
22433d6423SLionel Sambuc 
23433d6423SLionel Sambuc   out->iie_op = in->iie_op;
24433d6423SLionel Sambuc   out->iie_addr = in->iie_addr;
25433d6423SLionel Sambuc   out->iie_cmdlen = I2C_EXEC_MAX_CMDLEN < in->iie_cmdlen ?
26433d6423SLionel Sambuc   	I2C_EXEC_MAX_CMDLEN : in->iie_cmdlen;
27433d6423SLionel Sambuc   out->iie_buflen = I2C_EXEC_MAX_BUFLEN < in->iie_buflen ?
28433d6423SLionel Sambuc   	I2C_EXEC_MAX_BUFLEN : in->iie_buflen;
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc   if (in->iie_cmdlen > 0 && in->iie_cmd != NULL) {
31433d6423SLionel Sambuc 	memcpy(out->iie_cmd, in->iie_cmd, in->iie_cmdlen);
32433d6423SLionel Sambuc   }
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc   if (in->iie_buflen > 0 && in->iie_buf != NULL) {
35433d6423SLionel Sambuc 	memcpy(out->iie_buf, in->iie_buf, in->iie_buflen);
36433d6423SLionel Sambuc   }
37433d6423SLionel Sambuc }
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out,
40433d6423SLionel Sambuc 	minix_i2c_ioctl_exec_t *in)
41433d6423SLionel Sambuc {
42433d6423SLionel Sambuc   /* the only field that changes is iie_buf, everything else is the same */
4354841c01SEmmanuel Blot   if (in->iie_buflen > 0 ) {
44433d6423SLionel Sambuc 	memcpy(out->iie_buf, in->iie_buf, in->iie_buflen);
45433d6423SLionel Sambuc   }
46433d6423SLionel Sambuc }
47433d6423SLionel Sambuc 
48*ed223591SDavid van Moolenbroek /*
49*ed223591SDavid van Moolenbroek  * Library implementation of FIOCLEX and FIONCLEX.
50*ed223591SDavid van Moolenbroek  */
51*ed223591SDavid van Moolenbroek static int
52*ed223591SDavid van Moolenbroek ioctl_to_setfd(int fd, int mask, int val)
53*ed223591SDavid van Moolenbroek {
54*ed223591SDavid van Moolenbroek 	int fl;
55*ed223591SDavid van Moolenbroek 
56*ed223591SDavid van Moolenbroek 	if ((fl = fcntl(fd, F_GETFD)) == -1)
57*ed223591SDavid van Moolenbroek 		return -1;
58*ed223591SDavid van Moolenbroek 
59*ed223591SDavid van Moolenbroek 	fl = (fl & ~mask) | val;
60*ed223591SDavid van Moolenbroek 
61*ed223591SDavid van Moolenbroek 	return fcntl(fd, F_SETFD, fl);
62*ed223591SDavid van Moolenbroek }
63*ed223591SDavid van Moolenbroek 
64*ed223591SDavid van Moolenbroek /*
65*ed223591SDavid van Moolenbroek  * Library implementation of FIONBIO and FIOASYNC.
66*ed223591SDavid van Moolenbroek  */
67*ed223591SDavid van Moolenbroek static int
68*ed223591SDavid van Moolenbroek ioctl_to_setfl(int fd, void * data, int sfl)
69*ed223591SDavid van Moolenbroek {
70*ed223591SDavid van Moolenbroek 	int arg, fl;
71*ed223591SDavid van Moolenbroek 
72*ed223591SDavid van Moolenbroek 	arg = *(int *)data;
73*ed223591SDavid van Moolenbroek 
74*ed223591SDavid van Moolenbroek 	if ((fl = fcntl(fd, F_GETFL)) == -1)
75*ed223591SDavid van Moolenbroek 		return -1;
76*ed223591SDavid van Moolenbroek 
77*ed223591SDavid van Moolenbroek 	if (arg)
78*ed223591SDavid van Moolenbroek 		fl |= sfl;
79*ed223591SDavid van Moolenbroek 	else
80*ed223591SDavid van Moolenbroek 		fl &= ~sfl;
81*ed223591SDavid van Moolenbroek 
82*ed223591SDavid van Moolenbroek 	return fcntl(fd, F_SETFL, fl & ~O_ACCMODE);
83*ed223591SDavid van Moolenbroek }
84*ed223591SDavid van Moolenbroek 
85*ed223591SDavid van Moolenbroek /*
86*ed223591SDavid van Moolenbroek  * Library implementation of various deprecated IOCTLs.  These particular IOCTL
87*ed223591SDavid van Moolenbroek  * calls change how the file descriptors behave, and have nothing to do with
88*ed223591SDavid van Moolenbroek  * the actual open file.  They should therefore be handled by VFS rather than
89*ed223591SDavid van Moolenbroek  * individual device drivers.  We rewrite them to use fcntl(2) instead here.
90*ed223591SDavid van Moolenbroek  */
91*ed223591SDavid van Moolenbroek static int
92*ed223591SDavid van Moolenbroek ioctl_to_fcntl(int fd, unsigned long request, void * data)
93*ed223591SDavid van Moolenbroek {
94*ed223591SDavid van Moolenbroek 	switch (request) {
95*ed223591SDavid van Moolenbroek 	case FIOCLEX:
96*ed223591SDavid van Moolenbroek 		return ioctl_to_setfd(fd, FD_CLOEXEC, FD_CLOEXEC);
97*ed223591SDavid van Moolenbroek 	case FIONCLEX:
98*ed223591SDavid van Moolenbroek 		return ioctl_to_setfd(fd, FD_CLOEXEC, 0);
99*ed223591SDavid van Moolenbroek 	case FIONBIO:
100*ed223591SDavid van Moolenbroek 		return ioctl_to_setfl(fd, data, O_NONBLOCK);
101*ed223591SDavid van Moolenbroek 	case FIOASYNC:
102*ed223591SDavid van Moolenbroek 		return ioctl_to_setfl(fd, data, O_ASYNC);
103*ed223591SDavid van Moolenbroek 	case FIOSETOWN: /* XXX TODO */
104*ed223591SDavid van Moolenbroek 	case FIOGETOWN: /* XXX TODO */
105*ed223591SDavid van Moolenbroek 	default:
106*ed223591SDavid van Moolenbroek 		errno = ENOTTY;
107*ed223591SDavid van Moolenbroek 		return -1;
108*ed223591SDavid van Moolenbroek 	}
109*ed223591SDavid van Moolenbroek }
110*ed223591SDavid van Moolenbroek 
111433d6423SLionel Sambuc int     ioctl(int fd, unsigned long request, ...)
112433d6423SLionel Sambuc {
113433d6423SLionel Sambuc   int r, request_save;
114433d6423SLionel Sambuc   message m;
115433d6423SLionel Sambuc   vir_bytes addr;
116433d6423SLionel Sambuc   void *data;
117433d6423SLionel Sambuc   va_list ap;
118433d6423SLionel Sambuc 
119433d6423SLionel Sambuc   va_start(ap, request);
120433d6423SLionel Sambuc   data = va_arg(ap, void *);
121*ed223591SDavid van Moolenbroek   va_end(ap);
122433d6423SLionel Sambuc 
123433d6423SLionel Sambuc   /*
124433d6423SLionel Sambuc    * To support compatibility with interfaces on other systems, certain
125433d6423SLionel Sambuc    * requests are re-written to flat structures (i.e. without pointers).
126433d6423SLionel Sambuc    */
127433d6423SLionel Sambuc   minix_i2c_ioctl_exec_t i2c;
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   request_save = request;
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc   switch (request) {
132*ed223591SDavid van Moolenbroek 	case FIOCLEX:
133*ed223591SDavid van Moolenbroek 	case FIONCLEX:
134*ed223591SDavid van Moolenbroek 	case FIONBIO:
135*ed223591SDavid van Moolenbroek 	case FIOASYNC:
136*ed223591SDavid van Moolenbroek 	case FIOSETOWN:
137*ed223591SDavid van Moolenbroek 	case FIOGETOWN:
138*ed223591SDavid van Moolenbroek 		return ioctl_to_fcntl(fd, request, data);
139*ed223591SDavid van Moolenbroek 
140433d6423SLionel Sambuc 	case I2C_IOCTL_EXEC:
141433d6423SLionel Sambuc 		rewrite_i2c_netbsd_to_minix(&i2c, data);
142433d6423SLionel Sambuc 		addr = (vir_bytes) &i2c;
143433d6423SLionel Sambuc 		request = MINIX_I2C_IOCTL_EXEC;
144433d6423SLionel Sambuc 		break;
145433d6423SLionel Sambuc 	default:
146433d6423SLionel Sambuc 		/* Keep original as-is */
1475dd8da10SDavid van Moolenbroek 		addr = (vir_bytes)data;
148433d6423SLionel Sambuc 		break;
149433d6423SLionel Sambuc   }
150433d6423SLionel Sambuc 
151433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
152433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.fd = fd;
153433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.req = request;
154433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.arg = addr;
155433d6423SLionel Sambuc 
156433d6423SLionel Sambuc   r = _syscall(VFS_PROC_NR, VFS_IOCTL, &m);
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc   /* Translate back to original form */
159433d6423SLionel Sambuc   switch (request_save) {
160433d6423SLionel Sambuc 	case I2C_IOCTL_EXEC:
161433d6423SLionel Sambuc 		rewrite_i2c_minix_to_netbsd(data, &i2c);
162433d6423SLionel Sambuc 		break;
163433d6423SLionel Sambuc 	default:
164433d6423SLionel Sambuc 		/* Nothing to do */
165433d6423SLionel Sambuc 		break;
166433d6423SLionel Sambuc   }
167433d6423SLionel Sambuc 
168433d6423SLionel Sambuc   return r;
169433d6423SLionel Sambuc }
170