Skip to content

Commit

Permalink
Add SIGTERM handling for graceful job cancellation
Browse files Browse the repository at this point in the history
This squashed commit contains merged commits from 0.1.3-dev (de156c9)

Signals are now handled with the POSIX sigation(). A manual compile-time fallback to the ISO-specified signal() is available, see std.h

LBP2900/3000 LED may keep blinking during use if a job is cancelled after it starts blinking. The LED returns to normal when a job completes or is cancelled while the LED is off.

PPD files removed
  • Loading branch information
mounaiban committed Apr 26, 2020
1 parent dd4e069 commit 8cf7b6b
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 493 deletions.
353 changes: 0 additions & 353 deletions Canon-LBP2900-3000.ppd

This file was deleted.

94 changes: 0 additions & 94 deletions Canon-LBP3010.ppd

This file was deleted.

17 changes: 17 additions & 0 deletions src/capt-command.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

static uint8_t capt_iobuf[0x10000];
static size_t capt_iosize;
uint8_t sendrecv_status = NO_SENDRECV;

static void capt_debug_buf(const char *level, size_t size)
{
Expand Down Expand Up @@ -80,6 +81,7 @@ static void capt_send_buf(void)
(int) status);
exit(1);
}
sendrecv_status |= SENDRECV_SENT;
}
}
}
Expand All @@ -98,6 +100,7 @@ static void capt_recv_buf(size_t offset, size_t expected)
exit(1);
}
capt_iosize = offset + size;
sendrecv_status |= SENDRECV_RECVD;
}

const char *capt_identify(void)
Expand Down Expand Up @@ -145,6 +148,7 @@ void capt_send(uint16_t cmd, const void *buf, size_t size)

void capt_sendrecv(uint16_t cmd, const void *buf, size_t size, void *reply, size_t *reply_size)
{
sendrecv_status = (NO_SENDRECV | RECV_REQUIRED);
capt_send(cmd, buf, size);
capt_recv_buf(0, 6);
if (capt_iosize != 6 || WORD(capt_iobuf[0], capt_iobuf[1]) != cmd) {
Expand Down Expand Up @@ -202,3 +206,16 @@ void capt_multi_send(void)
capt_iobuf[3] = HI(capt_iosize);
capt_send_buf();
}

void capt_cleanup(void)
{
/* For use with handling job cancellations */
if (sendrecv_status && (RECV_REQUIRED || SENDRECV_SENT || !SENDRECV_RECVD) ){
uint8_t bs = 6;
if (capt_iosize > bs)
bs = capt_iosize;
cupsBackChannelRead(NULL, bs, 2);
sendrecv_status = NO_SENDRECV;
}
}

8 changes: 8 additions & 0 deletions src/capt-command.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ enum capt_command {
CAPT_GPIO = 0xE1A2,
};

enum capt_sendrecv_progress {
NO_SENDRECV = 0x00,
SENDRECV_SENT = 0x01,
SENDRECV_RECVD = 0x02,
RECV_REQUIRED = 0x04,
};


const char *capt_identify(void);

Expand All @@ -63,3 +70,4 @@ void capt_sendrecv(uint16_t cmd, const void *buf, size_t size, void *reply, size
void capt_multi_begin(uint16_t cmd);
void capt_multi_add(uint16_t cmd, const void *data, size_t size);
void capt_multi_send(void);
void capt_cleanup(void);
8 changes: 8 additions & 0 deletions src/printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <stdlib.h>
#include <string.h>

bool job_cancel = false;

struct printer_rec {
struct printer_rec *next;
const char *name;
Expand All @@ -49,6 +51,12 @@ static void __attribute__((destructor(101))) __clear_printers(void)
}
}

void cancel_job(int sig)
{
(void) sig;
job_cancel = true;
}

static bool ieee_isspace(char c)
{
switch (c) {
Expand Down
4 changes: 4 additions & 0 deletions src/printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ enum printer_support {
FULLY,
};

bool job_cancel;

struct page_dims_s;

struct printer_state_s {
Expand All @@ -51,11 +53,13 @@ struct printer_ops_s {
void *band, size_t size,
const void *pixels, unsigned line_size, unsigned num_lines);
void (*send_band) (struct printer_state_s *state, const void *band, size_t size);
void (*cancel_cleanup) (struct printer_state_s *state);
void (*wait_user) (struct printer_state_s *state);
};

const struct printer_ops_s *printer_detect(void);

void cancel_job(int sig);

void __printer_register_ops(const char *name, const struct printer_ops_s *ops,
enum printer_support status);
Expand Down
48 changes: 34 additions & 14 deletions src/prn_lbp2900.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static void lbp2900_wait_ready(const struct printer_ops_s *ops)

static void send_job_start(uint8_t fg, uint16_t page)
{
/* FIXME: this function could use a better name */

uint8_t ml = 0x00; /* host name lenght */
uint8_t ul = 0x00; /* user name lenght */
uint8_t nl = 0x00; /* document name lenght */
Expand Down Expand Up @@ -87,12 +89,12 @@ static const uint8_t magicbuf_2[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t lbp_2900_gpio_blink[] = {
static const uint8_t lbp2900_gpio_blink[] = {
0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00,
};

static const uint8_t lbp_2900_gpio_init[] = {
static const uint8_t lbp2900_gpio_init[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
Expand All @@ -103,7 +105,7 @@ static const uint8_t lbp_3010_gpio_blink[] = {
0x00, 0x00, 0x00, 0x00,
};

static const uint8_t lbp_3010_gpio_init[] = {
static const uint8_t lbp3010_gpio_init[] = {
/* led */ 0x13, 0x00, 0x00, /* S6 */ 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* S7 */ 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
Expand All @@ -122,7 +124,7 @@ static void lbp2900_job_prologue(struct printer_state_s *state)
lbp2900_get_status(state->ops);

capt_sendrecv(CAPT_START_0, NULL, 0, NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp_2900_gpio_init, ARRAY_SIZE(lbp_2900_gpio_init), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp2900_gpio_init, ARRAY_SIZE(lbp2900_gpio_init), NULL, 0);
capt_sendrecv(CAPT_JOB_BEGIN, magicbuf_0, ARRAY_SIZE(magicbuf_0), buf, &size);
job=WORD(buf[2], buf[3]);
lbp2900_wait_ready(state->ops);
Expand All @@ -142,21 +144,21 @@ static void lbp3000_job_prologue(struct printer_state_s *state)
lbp2900_get_status(state->ops);

capt_sendrecv(CAPT_START_0, NULL, 0, NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp_2900_gpio_init, ARRAY_SIZE(lbp_2900_gpio_init), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp2900_gpio_init, ARRAY_SIZE(lbp2900_gpio_init), NULL, 0);
capt_sendrecv(CAPT_JOB_BEGIN, magicbuf_0, ARRAY_SIZE(magicbuf_0), buf, &size);
job=WORD(buf[2], buf[3]);

/* LBP-3000 prints the very first printjob perfectly
* and then proceeds to hang at this (commented out)
* spot. That's the difference, or so it seems. */
/* lbp2900_wait_ready(state->ops); */
/* lbp2900_wait_ready(state->ops); */
send_job_start(1, 0);

/* There's also that command, that apparently does something, and does something,
* but it's there in the Wireshark logs. Response data == command data. */
uint8_t dummy[2] = {0, 0};
capt_sendrecv(0xE0A6, dummy, sizeof(dummy), NULL, 0);

lbp2900_wait_ready(state->ops);
}

Expand All @@ -175,7 +177,7 @@ static void lbp3010_job_prologue(struct printer_state_s *state)
capt_sendrecv(CAPT_JOB_BEGIN, magicbuf_0, ARRAY_SIZE(magicbuf_0), buf, &size);
job=WORD(buf[2], buf[3]);

capt_sendrecv(CAPT_GPIO, lbp_3010_gpio_init, ARRAY_SIZE(lbp_3010_gpio_init), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp3010_gpio_init, ARRAY_SIZE(lbp3010_gpio_init), NULL, 0);
lbp2900_wait_ready(state->ops);

send_job_start(1, 0);
Expand Down Expand Up @@ -374,8 +376,10 @@ static void lbp2900_job_epilogue(struct printer_state_s *state)

while (1) {
const struct capt_status_s *status = lbp2900_get_status(state->ops);
if (status->page_completed == status->page_decoding)
if (status->page_completed == status->page_decoding) {
send_job_start(4, status->page_completed); /* doin what the windows driver does*/
break;
}
sleep(1);
}
capt_sendrecv(CAPT_JOB_END, jbuf, 2, NULL, 0);
Expand All @@ -392,23 +396,37 @@ static void lbp2900_page_setup(struct printer_state_s *state,
dims->band_size = 70;
}

static void lbp2900_cancel_cleanup(struct printer_state_s *state)
{
(void) state;

capt_cleanup();
capt_sendrecv(CAPT_GPIO, lbp2900_gpio_init, ARRAY_SIZE(lbp2900_gpio_init), NULL, 0);
}

static void lbp3010_cancel_cleanup(struct printer_state_s *state)
{
(void) state;
capt_sendrecv(CAPT_GPIO, lbp3010_gpio_init, ARRAY_SIZE(lbp3010_gpio_init), NULL, 0);
}

static void lbp2900_wait_user(struct printer_state_s *state)
{
(void) state;

capt_sendrecv(CAPT_GPIO, lbp_2900_gpio_blink, ARRAY_SIZE(lbp_2900_gpio_blink), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp2900_gpio_blink, ARRAY_SIZE(lbp2900_gpio_blink), NULL, 0);
lbp2900_wait_ready(state->ops);

while (1) {
const struct capt_status_s *status = lbp2900_get_status(state->ops);
if (FLAG(status, CAPT_FL_BUTTON)) {
if (FLAG(status, CAPT_FL_BUTTON) || job_cancel) {
fprintf(stderr, "DEBUG: CAPT: button pressed\n");
break;
}
sleep(1);
}

capt_sendrecv(CAPT_GPIO, lbp_3010_gpio_init, ARRAY_SIZE(lbp_3010_gpio_init), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp2900_gpio_init, ARRAY_SIZE(lbp2900_gpio_init), NULL, 0);
lbp2900_wait_ready(state->ops);
}

Expand All @@ -432,7 +450,7 @@ static void lbp3010_wait_user(struct printer_state_s *state)
sleep(1);
}

capt_sendrecv(CAPT_GPIO, lbp_3010_gpio_init, ARRAY_SIZE(lbp_3010_gpio_init), NULL, 0);
capt_sendrecv(CAPT_GPIO, lbp3010_gpio_init, ARRAY_SIZE(lbp3010_gpio_init), NULL, 0);
lbp2900_wait_ready(state->ops);
}

Expand All @@ -445,6 +463,7 @@ static struct lbp2900_ops_s lbp2900_ops = {
.page_epilogue = lbp2900_page_epilogue,
.compress_band = ops_compress_band_hiscoa,
.send_band = ops_send_band_hiscoa,
.cancel_cleanup = lbp2900_cancel_cleanup,
.wait_user = lbp2900_wait_user,
},
.get_status = capt_get_xstatus,
Expand All @@ -462,14 +481,14 @@ static struct lbp2900_ops_s lbp3000_ops = {
.page_epilogue = lbp2900_page_epilogue,
.compress_band = ops_compress_band_hiscoa,
.send_band = ops_send_band_hiscoa,
.cancel_cleanup = lbp2900_cancel_cleanup,
.wait_user = lbp2900_wait_user,
},
.get_status = capt_get_xstatus,
.wait_ready = capt_wait_ready,
};

register_printer("LBP3000", lbp3000_ops.ops, EXPERIMENTAL);

static struct lbp2900_ops_s lbp3010_ops = {
.ops = {
.job_prologue = lbp3010_job_prologue,
Expand All @@ -479,6 +498,7 @@ static struct lbp2900_ops_s lbp3010_ops = {
.page_epilogue = lbp2900_page_epilogue,
.compress_band = ops_compress_band_hiscoa,
.send_band = ops_send_band_hiscoa,
.cancel_cleanup = lbp3010_cancel_cleanup,
.wait_user = lbp3010_wait_user,
},
.get_status = capt_get_xstatus_only,
Expand Down
Loading

1 comment on commit 8cf7b6b

@mounaiban
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sbn001 if you are reading this, here's another commit for you. This commit concludes another wave of changes that added two key features: paper button support on the LBP2900 (which you have already reported on) and preliminary support for graceful job cancellation.
The latter should allow you to resume from printing after cancelling a job without power cycling or reconnecting the printer. If we get the job cancellation right, then we will have made the first step towards a truly viable alternative to the Canon drivers.

Please test the job cancellation routine by starting a job, cancelling it, and finally starting another job. You should be able to continue without any trouble, save for a lag of about 5-10 seconds. Try cancelling the job at different stages, like before a page, during a page, when out of paper, etc... Let me know how things went with this commit, and happy printing! 📄

Please # to comment.