Created
May 31, 2024 09:09
-
-
Save pavly-gerges/352ca80aa6f7ce6c7ce156e55bccb3cc to your computer and use it in GitHub Desktop.
Linux `parport.h` IOCTL Magic Macros
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Any part of this program may be used in documents licensed under | |
* the GNU Free Documentation License, Version 1.1 or any later version | |
* published by the Free Software Foundation. | |
*/ | |
#ifndef _PARPORT_H_ | |
#define _PARPORT_H_ | |
/* Start off with user-visible constants */ | |
/* Maximum of 16 ports per machine */ | |
#define PARPORT_MAX 16 | |
/* Magic numbers */ | |
#define PARPORT_IRQ_NONE -1 | |
#define PARPORT_DMA_NONE -1 | |
#define PARPORT_IRQ_AUTO -2 | |
#define PARPORT_DMA_AUTO -2 | |
#define PARPORT_DMA_NOFIFO -3 | |
#define PARPORT_DISABLE -2 | |
#define PARPORT_IRQ_PROBEONLY -3 | |
#define PARPORT_IOHI_AUTO -1 | |
#define PARPORT_CONTROL_STROBE 0x1 | |
#define PARPORT_CONTROL_AUTOFD 0x2 | |
#define PARPORT_CONTROL_INIT 0x4 | |
#define PARPORT_CONTROL_SELECT 0x8 | |
#define PARPORT_STATUS_ERROR 0x8 | |
#define PARPORT_STATUS_SELECT 0x10 | |
#define PARPORT_STATUS_PAPEROUT 0x20 | |
#define PARPORT_STATUS_ACK 0x40 | |
#define PARPORT_STATUS_BUSY 0x80 | |
/* Type classes for Plug-and-Play probe. */ | |
typedef enum { | |
PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */ | |
PARPORT_CLASS_PRINTER, | |
PARPORT_CLASS_MODEM, | |
PARPORT_CLASS_NET, | |
PARPORT_CLASS_HDC, /* Hard disk controller */ | |
PARPORT_CLASS_PCMCIA, | |
PARPORT_CLASS_MEDIA, /* Multimedia device */ | |
PARPORT_CLASS_FDC, /* Floppy disk controller */ | |
PARPORT_CLASS_PORTS, | |
PARPORT_CLASS_SCANNER, | |
PARPORT_CLASS_DIGCAM, | |
PARPORT_CLASS_OTHER, /* Anything else */ | |
PARPORT_CLASS_UNSPEC, /* No CLS field in ID */ | |
PARPORT_CLASS_SCSIADAPTER | |
} parport_device_class; | |
/* The "modes" entry in parport is a bit field representing the | |
capabilities of the hardware. */ | |
#define PARPORT_MODE_PCSPP (1<<0) /* IBM PC registers available. */ | |
#define PARPORT_MODE_TRISTATE (1<<1) /* Can tristate. */ | |
#define PARPORT_MODE_EPP (1<<2) /* Hardware EPP. */ | |
#define PARPORT_MODE_ECP (1<<3) /* Hardware ECP. */ | |
#define PARPORT_MODE_COMPAT (1<<4) /* Hardware 'printer protocol'. */ | |
#define PARPORT_MODE_DMA (1<<5) /* Hardware can DMA. */ | |
#define PARPORT_MODE_SAFEININT (1<<6) /* SPP registers accessible in IRQ. */ | |
/* IEEE1284 modes: | |
Nibble mode, byte mode, ECP, ECPRLE and EPP are their own | |
'extensibility request' values. Others are special. | |
'Real' ECP modes must have the IEEE1284_MODE_ECP bit set. */ | |
#define IEEE1284_MODE_NIBBLE 0 | |
#define IEEE1284_MODE_BYTE (1<<0) | |
#define IEEE1284_MODE_COMPAT (1<<8) | |
#define IEEE1284_MODE_BECP (1<<9) /* Bounded ECP mode */ | |
#define IEEE1284_MODE_ECP (1<<4) | |
#define IEEE1284_MODE_ECPRLE (IEEE1284_MODE_ECP | (1<<5)) | |
#define IEEE1284_MODE_ECPSWE (1<<10) /* Software-emulated */ | |
#define IEEE1284_MODE_EPP (1<<6) | |
#define IEEE1284_MODE_EPPSL (1<<11) /* EPP 1.7 */ | |
#define IEEE1284_MODE_EPPSWE (1<<12) /* Software-emulated */ | |
#define IEEE1284_DEVICEID (1<<2) /* This is a flag */ | |
#define IEEE1284_EXT_LINK (1<<14) /* This flag causes the | |
* extensibility link to | |
* be requested, using | |
* bits 0-6. */ | |
/* For the benefit of parport_read/write, you can use these with | |
* parport_negotiate to use address operations. They have no effect | |
* other than to make parport_read/write use address transfers. */ | |
#define IEEE1284_ADDR (1<<13) /* This is a flag */ | |
#define IEEE1284_DATA 0 /* So is this */ | |
/* Flags for block transfer operations. */ | |
#define PARPORT_EPP_FAST (1<<0) /* Unreliable counts. */ | |
#define PARPORT_W91284PIC (1<<1) /* have a Warp9 w91284pic in the device */ | |
/* The rest is for the kernel only */ | |
#endif /* _PARPORT_H_ */ |
While directly controlling all 25 pins of a parallel port might not be practical for most uses due to limitations of the data pins (8) and special purpose pins, here's an enhanced example demonstrating operations on various parallel port pins:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/parport.h>
#define PARPORT_DEVICE "/dev/parport0"
int main(int argc, char *argv[]) {
int fd, ret;
unsigned char data;
// Open the parallel port device file
fd = open(PARPORT_DEVICE, O_RDWR);
if (fd == -1) {
perror("Failed to open parallel port");
return 1;
}
// Data pins (D0-D7) - Output specific values
printf("Setting data pins:\n");
for (int i = 0; i < 8; i++) {
data = 1 << i; // Set each bit individually for specific data pattern
ret = ioctl(fd, PPWDATA, &data);
if (ret == -1) {
perror("Failed to write to data pin");
close(fd);
return 1;
}
printf(" - D%d: 0x%02X\n", i, data);
}
// Control pins (e.g., Strobe, Select, AutoFeed) - Set and Read
printf("Control pins:\n");
// Set Strobe pin (pin 1) high
data = PARPORT_CONTROL_STROBE; // Use defined constants from parport.h
ret = ioctl(fd, PPWCONTROL, &data);
if (ret == -1) {
perror("Failed to write to control pin");
close(fd);
return 1;
}
printf(" - Strobe (pin 1): HIGH\n");
// Read the state of all control pins
data = 0;
ret = ioctl(fd, PPRCONTROL, &data);
if (ret == -1) {
perror("Failed to read control pins");
close(fd);
return 1;
}
printf(" - Current state: 0x%02X\n", data);
// Status pins (e.g., Busy, PaperOut) - Read only (example)
printf("Status pins (read-only):\n");
data = 0;
ret = ioctl(fd, PPRSTATUS, &data); // Might not work on all systems
if (ret == -1) {
perror("Failed to read status pin");
} else {
printf(" - Status register: 0x%02X\n", data);
}
// Close the device file
close(fd);
return 0;
}
Explanation:
- The code includes necessary header files and defines the device file path.
- It opens the device file with read/write access.
- It iterates through each data pin (D0-D7) and sets it high (1) individually using bit manipulation (
1 << i
). - It sets the Strobe control pin (pin 1) high using the
PARPORT_CONTROL_STROBE
constant fromlinux/parport.h
. - It reads the current state of all control pins using
PPRCONTROL
. - It attempts to read the status register using
PPRSTATUS
(might not work on all systems as these pins are often read-only).
Important Notes:
- This example demonstrates basic operations. Refer to
linux/parport.h
for a complete list of ioctls, constants, and pin definitions. - Remember, parallel port access requires root privileges.
- Modern systems might not have
libppdev
pre-installed. You might need to install the development package for theppdev
driver. - Consider error handling and safety measures in real-world applications.
Additional Considerations:
- Data pins (D0-D7) can be used for bi-directional communication, but some external hardware might require specific configurations (e.g., setting data direction using control pins).
- Not all control and status pins might be available on all parallel port implementations. Consult your system's documentation for specific pin functionalities.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Responses from Gemini:
Here's an example program (C code) demonstrating basic operations on the parallel port using
ioctl
and theppdev
driver:Explanation:
PARPORT_DEVICE
) for the parallel port (usually/dev/parport0
).O_RDWR
).0x80
(binary: 10000000) to the data port using thePPWDATA
ioctl.PPRCONTROL
and prints the value.0x01
(binary: 00000001) and then0xFE
(all data pins high except D0).Compiling and Running:
.c
file (e.g.,parallel_test.c
).sudo
when compiling:libppdev
library (if available).sudo ./parallel_test
.Important Notes:
linux/parport.h
header for a complete list of ioctls and their arguments.libppdev
pre-installed. You might need to install the development package for theppdev
driver.