]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/ieee1394-linux.c
2 * "$Id: ieee1394-linux.c 6649 2007-07-11 21:46:42Z mike $"
4 * Linux IEEE-1394 glue for the Common UNIX Printing System (CUPS).
6 * Copyright 2007 by Apple Inc.
7 * Copyright 2002 by Easy Software Products, all rights reserved.
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the
11 * following conditions are met:
13 * 1. Redistributions of source code must retain the above
14 * copyright notice, this list of conditions and the
15 * following disclaimer.
17 * 2. Redistributions in binary form must reproduce the
18 * above copyright notice, this list of conditions and
19 * the following disclaimer in the documentation and/or
20 * other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use
23 * of this software must display the following
26 * This product includes software developed by Easy
29 * 4. The name of Easy Software Products may not be used to
30 * endorse or promote products derived from this software
31 * without specific prior written permission.
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
34 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
35 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
44 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
50 * get_device_id() - Get the IEEE-1284 device ID for a node...
51 * get_unit_type() - Get the unit type for a node...
52 * show_data() - Show a data node...
53 * show_dir() - Show a directory list...
54 * ieee1394_list() - List the available printer devices.
55 * ieee1394_open() - Open a printer device.
56 * ieee1394_close() - Close a printer device.
57 * ieee1394_read() - Read from a printer device.
58 * ieee1394_write() - Write data to a printer device.
59 * ieee1394_error() - Return the last error.
63 * Include necessary headers.
67 #include <cups/debug.h>
68 #include <libraw1394/raw1394.h>
69 #include <libraw1394/csr.h>
85 char uri
[HTTP_MAX_URI
],/* URI for this node... */
86 description
[128],/* Description of port */
87 make_model
[128];/* Make and model */
88 int port
, /* Port where this node is found */
89 node
; /* Node number */
90 unsigned long long addr
; /* Management address */
95 raw1394handle_t handle
; /* Handle for printer device */
96 int node
; /* Node number for printer device */
97 unsigned long long addr
; /* Management address */
102 * ORB messages for communication with the device...
105 typedef struct /**** Login ORB Message */
107 unsigned char passwd_addr
[8]; /* Password address */
108 unsigned char resp_addr
[8]; /* Login response address */
109 unsigned char notify_excl
; /* Notify and exclusive bits */
110 unsigned char recon_func
; /* Reconnect time and function */
111 unsigned char lun
[2]; /* Logical unit number */
112 unsigned char passwd_len
[2]; /* Length of password */
113 unsigned char resp_len
[2]; /* Length of login response */
114 unsigned char fifo_addr
[8]; /* Local status FIFO address */
117 typedef struct /**** Login Response Message ****/
119 unsigned char length
[2]; /* Length of response */
120 unsigned char login_id
[2]; /* Login ID */
121 unsigned char cmd_addr
[8]; /* Command block agent address */
122 unsigned char reserved
[2]; /* Reserved (0) */
123 unsigned char recon_hold
[2]; /* Number of seconds to hold login */
131 static char error_string
[1024] = "";
132 static int num_nodes
;
133 static linux1394_node_t nodes
[MAX_NODES
];
137 * 'get_device_id()' - Get the IEEE-1284 device ID for a node...
140 static char * /* O - Device ID */
141 get_device_id(raw1394handle_t handle
,/* I - Handle for device */
142 int node
, /* I - Node number */
143 unsigned long long offset
,/* I - Offset to directory */
144 char *id
, /* O - ID string */
145 int idlen
) /* I - Size of ID string */
147 unsigned char data
[1024], /* Data from ROM */
148 *dataptr
; /* Pointer into data */
149 int length
; /* Length of directory */
150 int datalen
; /* Length of data */
151 unsigned long long dataoff
; /* Offset of data */
154 DEBUG_printf(("get_device_id(handle = %p, node = %d, offset = %llx, id = %p, idlen = %d)\n",
155 handle
, node
, offset
, id
, idlen
));
160 * Read the directory length from the first quadlet...
163 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
169 * The length is in the upper 16 bits...
172 length
= (data
[0] << 8) | data
[1];
174 DEBUG_printf((" length = %d\n", length
));
177 * Then read the directory, looking for unit directory or device tags...
182 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
185 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
191 * Found the unit directory...
194 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
196 return (get_device_id(handle
, node
, offset
, id
, idlen
));
198 else if (data
[0] == 0x81)
201 * Found potential IEEE-1284 device ID...
204 dataoff
= offset
+ (((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2);
206 if (raw1394_read(handle
, 0xffc0 | node
, dataoff
, 4, (quadlet_t
*)data
) < 0)
212 * Read the leaf value...
215 datalen
= (data
[0] << 8) | data
[1];
217 if (datalen
> (sizeof(data
) / 4))
218 datalen
= sizeof(data
) / 4;
220 for (dataptr
= data
; datalen
> 0; datalen
--, dataptr
+= 4, dataoff
+= 4)
221 if (raw1394_read(handle
, 0xffc0 | node
, dataoff
, 4,
222 (quadlet_t
*)dataptr
) < 0)
225 if (data
[0] == 0 && memcmp(data
+ 8, "MFG:", 4) == 0)
228 * Found the device ID...
231 datalen
= dataptr
- data
- 8;
232 if (datalen
>= idlen
)
235 memcpy(id
, data
+ 8, datalen
);
251 * 'get_man_addr()' - Get the management address for a node...
254 static int /* O - Unit type */
255 get_man_addr(raw1394handle_t handle
, /* I - Handle for device */
256 int node
, /* I - Node number */
257 unsigned long long offset
) /* I - Offset to directory */
259 unsigned char data
[4]; /* Data from ROM */
260 int length
; /* Length of directory */
263 DEBUG_printf(("get_man_addr(handle = %p, node = %d, offset = %llx)\n",
264 handle
, node
, offset
));
267 * Read the directory length from the first quadlet...
270 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
276 * The length is in the upper 16 bits...
279 length
= (data
[0] << 8) | data
[1];
281 DEBUG_printf((" length = %d\n", length
));
284 * Then read the directory, looking for unit directory or type tags...
289 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
292 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
298 * Found the unit directory...
301 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
303 return (get_man_addr(handle
, node
, offset
));
305 else if (data
[0] == 0x54)
308 * Found the management address...
311 return (((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2);
323 * 'get_unit_type()' - Get the unit type for a node...
326 static int /* O - Unit type */
327 get_unit_type(raw1394handle_t handle
,/* I - Handle for device */
328 int node
, /* I - Node number */
329 unsigned long long offset
)/* I - Offset to directory */
331 unsigned char data
[4]; /* Data from ROM */
332 int length
; /* Length of directory */
335 DEBUG_printf(("get_unit_type(handle = %p, node = %d, offset = %llx)\n",
336 handle
, node
, offset
));
339 * Read the directory length from the first quadlet...
342 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
348 * The length is in the upper 16 bits...
351 length
= (data
[0] << 8) | data
[1];
353 DEBUG_printf((" length = %d\n", length
));
356 * Then read the directory, looking for unit directory or type tags...
361 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
364 DEBUG_printf((" data = %02X %02X %02X %02X\n", data
[0], data
[1],
370 * Found the unit directory...
373 offset
+= ((((data
[1] << 8) | data
[2]) << 8) | data
[3]) << 2;
375 return (get_unit_type(handle
, node
, offset
));
377 else if (data
[0] == 0x14)
380 * Found the unit type...
383 return (data
[1] & 0x1f);
396 * 'show_data()' - Show a data node...
400 show_data(raw1394handle_t handle
, /* I - Handle for device */
401 int node
, /* I - Node number */
402 unsigned long long offset
, /* I - Offset to directory */
403 int indent
) /* Amount to indent */
405 int i
; /* Looping var */
406 unsigned char data
[4]; /* Data from ROM */
407 int length
; /* Length of data */
411 * Read the data length from the first quadlet...
414 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
420 * The length is in the upper 16 bits...
423 length
= (data
[0] << 8) | data
[1];
426 * Then read the data...
429 for (i
= 0; i
< indent
; i
++)
432 printf("LEAF (%d quadlets)\n", length
);
436 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
439 for (i
= 0; i
< indent
; i
++)
442 printf("%02X %02X %02X %02X '%c%c%c%c'\n",
443 data
[0], data
[1], data
[2], data
[3],
444 (data
[0] < ' ' || data
[0] >= 0x7f) ? '.' : data
[0],
445 (data
[1] < ' ' || data
[1] >= 0x7f) ? '.' : data
[1],
446 (data
[2] < ' ' || data
[2] >= 0x7f) ? '.' : data
[2],
447 (data
[3] < ' ' || data
[3] >= 0x7f) ? '.' : data
[3]);
456 * 'show_dir()' - Show a directory list...
460 show_dir(raw1394handle_t handle
, /* I - Handle for device */
461 int node
, /* I - Node number */
462 unsigned long long offset
, /* I - Offset to directory */
463 int indent
) /* Amount to indent */
465 int i
; /* Looping var */
466 unsigned char data
[4]; /* Data from ROM */
467 int length
; /* Length of directory */
468 int value
; /* Value in directory */
472 * Read the directory length from the first quadlet...
475 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
481 * The length is in the upper 16 bits...
484 length
= (data
[0] << 8) | data
[1];
487 * Then read the directory...
492 if (raw1394_read(handle
, 0xffc0 | node
, offset
, 4, (quadlet_t
*)data
) < 0)
495 for (i
= 0; i
< indent
; i
++)
498 printf("%02X %02X %02X %02X\n", data
[0], data
[1], data
[2], data
[3]);
500 value
= (((data
[1] << 8) | data
[2]) << 8) | data
[3];
502 switch (data
[0] & 0xc0)
505 for (i
= -4; i
< indent
; i
++)
508 printf("IMMEDIATE %d\n", value
);
512 for (i
= -4; i
< indent
; i
++)
515 printf("CSR OFFSET +%06X\n", value
);
519 show_data(handle
, node
, offset
+ value
* 4, indent
+ 4);
523 show_dir(handle
, node
, offset
+ value
* 4, indent
+ 4);
535 * 'ieee1394_list()' - List the available printer devices.
538 ieee1394_info_t
* /* O - Printer information */
539 ieee1394_list(int *num_devices
) /* O - Number of printers */
541 int i
, j
; /* Looping vars */
542 raw1394handle_t handle
; /* 1394 handle */
543 int num_ports
; /* Number of ports */
544 struct raw1394_portinfo ports
[100]; /* Port data... */
545 unsigned char guid
[8]; /* Global unique ID */
546 int vendor
; /* Vendor portion of GUID */
547 int unit_type
; /* Unit type */
548 int addr
; /* Management address offset */
549 char id
[1024], /* Device ID string */
550 *idptr
, /* Pointer into ID string */
551 *idsep
; /* Pointer to separator */
552 ieee1394_info_t
*devices
; /* Device list */
556 * Connect to the user-mode driver interface...
559 handle
= raw1394_new_handle();
560 num_ports
= raw1394_get_port_info(handle
, ports
,
561 sizeof(ports
) / sizeof(ports
[0]));
563 DEBUG_printf(("num_ports = %d\n", num_ports
));
566 * Loop through the ports to discover what nodes are available.
571 for (i
= 0; i
< num_ports
; i
++)
573 DEBUG_printf(("ports[%d] = { nodes = %d, name = \"%s\" }\n", i
,
574 ports
[i
].nodes
, ports
[i
].name
));
576 raw1394_set_port(handle
, i
);
578 for (j
= 0; j
< ports
[i
].nodes
; j
++)
580 if (raw1394_read(handle
, 0xffc0 | j
,
581 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 12, 4,
582 (quadlet_t
*)guid
) < 0)
584 DEBUG_printf((" Node #%d: Unable to contact (%s)!\n", j
,
590 raw1394_read(handle
, 0xffc0 | j
,
591 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 16, 4,
592 (quadlet_t
*)(guid
+ 4));
594 DEBUG_printf((" Node #%d: GUID = %02X%02X%02X%02X%02X%02X%02X%02X\n",
595 j
, guid
[0], guid
[1], guid
[2], guid
[3], guid
[4],
596 guid
[5], guid
[6], guid
[7]));
598 vendor
= (((guid
[0] << 8) | guid
[1]) << 8) | guid
[2];
599 unit_type
= get_unit_type(handle
, j
,
600 CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20);
602 DEBUG_printf(("vendor = %x, unit_type = %d\n", vendor
, unit_type
));
604 if (unit_type
== 2 && num_nodes
< MAX_NODES
)
607 * Found a printer device; add it to the nodes list...
611 show_dir(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20, 0);
614 memset(nodes
+ num_nodes
, 0, sizeof(linux1394_node_t
));
616 sprintf(nodes
[num_nodes
].uri
, "ieee1394://%02X%02X%02X%02X%02X%02X%02X%02X",
617 guid
[0], guid
[1], guid
[2], guid
[3], guid
[4],
618 guid
[5], guid
[6], guid
[7]);
620 nodes
[num_nodes
].port
= i
;
621 nodes
[num_nodes
].node
= j
;
623 addr
= get_man_addr(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20);
628 nodes
[num_nodes
].addr
= CSR_REGISTER_BASE
+ addr
;
630 DEBUG_printf(("Node address = %llx\n", nodes
[num_nodes
].addr
));
632 get_device_id(handle
, j
, CSR_REGISTER_BASE
+ CSR_CONFIG_ROM
+ 20,
638 * Grab the manufacturer and model name from the device ID
643 idsep
= strchr(id
, ';');
649 snprintf(nodes
[num_nodes
].description
,
650 sizeof(nodes
[num_nodes
].description
),
651 "%s Firewire Printer", idptr
);
653 if ((idptr
= strstr(idsep
, "DES:")) == NULL
)
654 idptr
= strstr(idsep
, "MDL:");
657 strcpy(nodes
[num_nodes
].make_model
, "Unknown");
661 * Grab the DES or MDL code...
665 idsep
= strchr(idptr
, ';');
669 if (strncmp(id
+ 4, idptr
, strlen(id
+ 4)) == 0)
672 * Use the description directly...
675 strlcpy(nodes
[num_nodes
].make_model
, idptr
,
676 sizeof(nodes
[num_nodes
].make_model
));
681 * Add the manufacturer to the front of the name...
684 snprintf(nodes
[num_nodes
].make_model
,
685 sizeof(nodes
[num_nodes
].make_model
),
686 "%s %s", id
+ 4, idptr
);
693 * Flag it as an unknown printer...
696 sprintf(nodes
[num_nodes
].description
,
697 "Unknown%06X Firewire Printer", vendor
);
698 strcpy(nodes
[num_nodes
].make_model
, "Unknown");
708 * Done querying the Firewire bus...
711 raw1394_destroy_handle(handle
);
714 * Build an array of device info structures as needed...
717 if (num_devices
== NULL
)
720 *num_devices
= num_nodes
;
724 if ((devices
= calloc(sizeof(ieee1394_info_t
), num_nodes
)) != NULL
)
726 for (i
= 0; i
< num_nodes
; i
++)
728 strcpy(devices
[i
].uri
, nodes
[i
].uri
);
729 strcpy(devices
[i
].description
, nodes
[i
].description
);
730 strcpy(devices
[i
].make_model
, nodes
[i
].make_model
);
742 * 'ieee1394_open()' - Open a printer device.
745 ieee1394_dev_t
/* O - Printer device or NULL */
746 ieee1394_open(const char *uri
) /* I - Device URI */
748 int i
; /* Looping var */
749 linux1394_dev_t
*ldev
; /* Linux device */
753 * Return early if we can't see any printers...
761 strcpy(error_string
, "No IEEE-1394 printers found!");
766 * Look for the URI...
769 for (i
= 0; i
< num_nodes
; i
++)
770 if (strcmp(nodes
[i
].uri
, uri
) == 0)
775 snprintf(error_string
, sizeof(error_string
), "Device %s not found!", uri
);
780 * Now create a new device structure...
783 if ((ldev
= calloc(sizeof(linux1394_dev_t
), 1)) == NULL
)
785 strcpy(error_string
, "Out of memory!");
789 ldev
->handle
= raw1394_new_handle();
790 ldev
->node
= nodes
[i
].node
;
791 ldev
->addr
= nodes
[i
].addr
;
793 raw1394_set_port(ldev
->handle
, nodes
[i
].port
);
795 error_string
[0] = '\0';
797 return ((ieee1394_dev_t
)ldev
);
802 * 'ieee1394_close()' - Close a printer device.
805 int /* O - 0 on success, -1 on failure */
806 ieee1394_close(ieee1394_dev_t dev
) /* I - Printer device */
808 linux1394_dev_t
*ldev
; /* Linux device */
811 ldev
= (linux1394_dev_t
*)dev
;
813 raw1394_destroy_handle(ldev
->handle
);
822 * 'ieee1394_read()' - Read from a printer device.
825 int /* O - Number of bytes read or -1 */
826 ieee1394_read(ieee1394_dev_t dev
, /* I - Printer device */
827 char *buffer
, /* I - Read buffer */
828 int len
) /* I - Max bytes to read */
830 linux1394_dev_t
*ldev
; /* Linux device */
833 ldev
= (linux1394_dev_t
*)dev
;
841 * 'ieee1394_write()' - Write data to a printer device.
844 int /* O - Number of bytes written or -1 */
845 ieee1394_write(ieee1394_dev_t dev
, /* I - Printer device */
846 char *buffer
, /* I - Buffer to write */
847 int len
) /* I - Number of bytes to write */
849 linux1394_dev_t
*ldev
; /* Linux device */
852 ldev
= (linux1394_dev_t
*)dev
;
855 /* if (raw1394_write(handle, 0xffc0 | j, 0, ,
856 (quadlet_t *)guid) < 0)*/
863 * 'ieee1394_error()' - Return the last error.
866 const char * /* O - Error string or NULL */
870 return (error_string
);
877 * End of "$Id: ieee1394-linux.c 6649 2007-07-11 21:46:42Z mike $".