xref: /minix3/minix/lib/libc/sys/ioctl.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include <sys/cdefs.h>
2*433d6423SLionel Sambuc #include "namespace.h"
3*433d6423SLionel Sambuc #include <lib.h>
4*433d6423SLionel Sambuc #include <stdarg.h>
5*433d6423SLionel Sambuc 
6*433d6423SLionel Sambuc #include <sys/ioctl.h>
7*433d6423SLionel Sambuc #include <minix/i2c.h>
8*433d6423SLionel Sambuc #include <string.h>
9*433d6423SLionel Sambuc #include <sys/ioccom.h>
10*433d6423SLionel Sambuc #include <stdarg.h>
11*433d6423SLionel Sambuc 
12*433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out,
13*433d6423SLionel Sambuc     i2c_ioctl_exec_t *in);
14*433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out,
15*433d6423SLionel Sambuc     minix_i2c_ioctl_exec_t *in);
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t *out,
18*433d6423SLionel Sambuc 	i2c_ioctl_exec_t *in)
19*433d6423SLionel Sambuc {
20*433d6423SLionel Sambuc   memset(out, '\0', sizeof(minix_i2c_ioctl_exec_t));
21*433d6423SLionel Sambuc 
22*433d6423SLionel Sambuc   out->iie_op = in->iie_op;
23*433d6423SLionel Sambuc   out->iie_addr = in->iie_addr;
24*433d6423SLionel Sambuc   out->iie_cmdlen = I2C_EXEC_MAX_CMDLEN < in->iie_cmdlen ?
25*433d6423SLionel Sambuc   	I2C_EXEC_MAX_CMDLEN : in->iie_cmdlen;
26*433d6423SLionel Sambuc   out->iie_buflen = I2C_EXEC_MAX_BUFLEN < in->iie_buflen ?
27*433d6423SLionel Sambuc   	I2C_EXEC_MAX_BUFLEN : in->iie_buflen;
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc   if (in->iie_cmdlen > 0 && in->iie_cmd != NULL) {
30*433d6423SLionel Sambuc 	memcpy(out->iie_cmd, in->iie_cmd, in->iie_cmdlen);
31*433d6423SLionel Sambuc   }
32*433d6423SLionel Sambuc 
33*433d6423SLionel Sambuc   if (in->iie_buflen > 0 && in->iie_buf != NULL) {
34*433d6423SLionel Sambuc 	memcpy(out->iie_buf, in->iie_buf, in->iie_buflen);
35*433d6423SLionel Sambuc   }
36*433d6423SLionel Sambuc }
37*433d6423SLionel Sambuc 
38*433d6423SLionel Sambuc static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t *out,
39*433d6423SLionel Sambuc 	minix_i2c_ioctl_exec_t *in)
40*433d6423SLionel Sambuc {
41*433d6423SLionel Sambuc   /* the only field that changes is iie_buf, everything else is the same */
42*433d6423SLionel Sambuc   if (in->iie_buflen > 0 && in->iie_buf != NULL) {
43*433d6423SLionel Sambuc 	memcpy(out->iie_buf, in->iie_buf, in->iie_buflen);
44*433d6423SLionel Sambuc   }
45*433d6423SLionel Sambuc }
46*433d6423SLionel Sambuc 
47*433d6423SLionel Sambuc int     ioctl(int fd, unsigned long request, ...)
48*433d6423SLionel Sambuc {
49*433d6423SLionel Sambuc   int r, request_save;
50*433d6423SLionel Sambuc   message m;
51*433d6423SLionel Sambuc   vir_bytes addr;
52*433d6423SLionel Sambuc   void *data;
53*433d6423SLionel Sambuc   va_list ap;
54*433d6423SLionel Sambuc 
55*433d6423SLionel Sambuc   va_start(ap, request);
56*433d6423SLionel Sambuc   data = va_arg(ap, void *);
57*433d6423SLionel Sambuc 
58*433d6423SLionel Sambuc   /*
59*433d6423SLionel Sambuc    * To support compatibility with interfaces on other systems, certain
60*433d6423SLionel Sambuc    * requests are re-written to flat structures (i.e. without pointers).
61*433d6423SLionel Sambuc    */
62*433d6423SLionel Sambuc   minix_i2c_ioctl_exec_t i2c;
63*433d6423SLionel Sambuc 
64*433d6423SLionel Sambuc   request_save = request;
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc   switch (request) {
67*433d6423SLionel Sambuc 	case I2C_IOCTL_EXEC:
68*433d6423SLionel Sambuc 		rewrite_i2c_netbsd_to_minix(&i2c, data);
69*433d6423SLionel Sambuc 		addr = (vir_bytes) &i2c;
70*433d6423SLionel Sambuc 		request = MINIX_I2C_IOCTL_EXEC;
71*433d6423SLionel Sambuc 		break;
72*433d6423SLionel Sambuc 	default:
73*433d6423SLionel Sambuc 		/* Keep original as-is */
74*433d6423SLionel Sambuc 		addr = data;
75*433d6423SLionel Sambuc 		break;
76*433d6423SLionel Sambuc   }
77*433d6423SLionel Sambuc 
78*433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
79*433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.fd = fd;
80*433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.req = request;
81*433d6423SLionel Sambuc   m.m_lc_vfs_ioctl.arg = addr;
82*433d6423SLionel Sambuc 
83*433d6423SLionel Sambuc   r = _syscall(VFS_PROC_NR, VFS_IOCTL, &m);
84*433d6423SLionel Sambuc 
85*433d6423SLionel Sambuc   /* Translate back to original form */
86*433d6423SLionel Sambuc   switch (request_save) {
87*433d6423SLionel Sambuc 	case I2C_IOCTL_EXEC:
88*433d6423SLionel Sambuc 		rewrite_i2c_minix_to_netbsd(data, &i2c);
89*433d6423SLionel Sambuc 		break;
90*433d6423SLionel Sambuc 	default:
91*433d6423SLionel Sambuc 		/* Nothing to do */
92*433d6423SLionel Sambuc 		break;
93*433d6423SLionel Sambuc   }
94*433d6423SLionel Sambuc 
95*433d6423SLionel Sambuc   va_end(ap);
96*433d6423SLionel Sambuc 
97*433d6423SLionel Sambuc   return r;
98*433d6423SLionel Sambuc }
99