static int camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) { unsigned char *frame_data; unsigned char *ppm, *ptr; unsigned char gtable[256]; int size; int w = 320; int h = 240; int b=0x12c40; camera->pl->last_fetched_data = malloc (b); if (!camera->pl->last_fetched_data) { sq_rewind(camera->port, camera->pl); return GP_ERROR_NO_MEMORY; } sq_access_reg(camera->port, CAPTURE); sq_read_picture_data (camera->port, camera->pl->last_fetched_data, b); frame_data = camera->pl->last_fetched_data + 0x40; sq_preprocess(camera->pl->model, 1, 0, frame_data, w, h); /* Now put the data into a PPM image file. */ ppm = malloc (w * h * 3 + 256); if (!ppm) return GP_ERROR_NO_MEMORY; sprintf ((char *)ppm, "P6\n" "# CREATOR: gphoto2, SQ905 library\n" "%d %d\n" "255\n", w, h); ptr = ppm + strlen ((char*)ppm); size = strlen ((char*)ppm) + (w * h * 3); GP_DEBUG ("size = %i\n", size); switch (camera->pl->model) { case SQ_MODEL_POCK_CAM: gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_GBRG); break; default: gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_BGGR); break; } /* TO DO: * Adapt some postprocessing routine to work here, because results * can vary greatly, depending both on lighting conditions and on * camera model. */ gp_gamma_fill_table (gtable, .5); gp_gamma_correct_single (gtable, ptr, w * h); gp_file_set_mime_type (file, GP_MIME_PPM); gp_file_set_data_and_size (file, (char *)ppm, size); sq_reset(camera->port); sq_access_reg(camera->port, CAPTURE); sq_reset(camera->port); return (GP_OK); }
static int camera_exit (Camera *camera, GPContext *context) { GP_DEBUG ("SQ camera_exit"); sq_reset (camera->port); if (camera->pl) { free (camera->pl->catalog); free (camera->pl->last_fetched_data); free (camera->pl); camera->pl = NULL; } return GP_OK; }
void sq_stop(struct ifnet *ifp, int disable) { int i; struct sq_softc *sc = ifp->if_softc; for (i =0; i < SQ_NTXDESC; i++) { if (sc->sc_txmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_txmap[i]); m_freem(sc->sc_txmbuf[i]); sc->sc_txmbuf[i] = NULL; } } /* Clear Seeq transmit/receive command registers */ bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, 0); bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_RXCMD, 0); sq_reset(sc); ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ifp->if_timer = 0; }
static void sq_attach(struct device *parent, struct device *self, void *aux) { int i, err; char* macaddr; struct sq_softc *sc = (void *)self; struct hpc_attach_args *haa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; sc->sc_hpct = haa->ha_st; if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, HPC_ENET_REGS_SIZE, &sc->sc_hpch)) != 0) { printf(": unable to map HPC DMA registers, error = %d\n", err); goto fail_0; } sc->sc_regt = haa->ha_st; if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, HPC_ENET_DEVREGS_SIZE, &sc->sc_regh)) != 0) { printf(": unable to map Seeq registers, error = %d\n", err); goto fail_0; } sc->sc_dmat = haa->ha_dmat; if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sq_control), PAGE_SIZE, PAGE_SIZE, &sc->sc_cdseg, 1, &sc->sc_ncdseg, BUS_DMA_NOWAIT)) != 0) { printf(": unable to allocate control data, error = %d\n", err); goto fail_0; } if ((err = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg, sizeof(struct sq_control), (caddr_t *)&sc->sc_control, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { printf(": unable to map control data, error = %d\n", err); goto fail_1; } if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct sq_control), 1, sizeof(struct sq_control), PAGE_SIZE, BUS_DMA_NOWAIT, &sc->sc_cdmap)) != 0) { printf(": unable to create DMA map for control data, error " "= %d\n", err); goto fail_2; } if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cdmap, sc->sc_control, sizeof(struct sq_control), NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load DMA map for control data, error " "= %d\n", err); goto fail_3; } memset(sc->sc_control, 0, sizeof(struct sq_control)); /* Create transmit buffer DMA maps */ for (i = 0; i < SQ_NTXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_txmap[i])) != 0) { printf(": unable to create tx DMA map %d, error = %d\n", i, err); goto fail_4; } } /* Create transmit buffer DMA maps */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_rxmap[i])) != 0) { printf(": unable to create rx DMA map %d, error = %d\n", i, err); goto fail_5; } } /* Pre-allocate the receive buffers. */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = sq_add_rxbuf(sc, i)) != 0) { printf(": unable to allocate or map rx buffer %d\n," " error = %d\n", i, err); goto fail_6; } } if ((macaddr = ARCBIOS->GetEnvironmentVariable("eaddr")) == NULL) { printf(": unable to get MAC address!\n"); goto fail_6; } evcnt_attach_dynamic(&sc->sq_intrcnt, EVCNT_TYPE_INTR, NULL, self->dv_xname, "intr"); if ((cpu_intr_establish(haa->ha_irq, IPL_NET, sq_intr, sc)) == NULL) { printf(": unable to establish interrupt!\n"); goto fail_6; } /* Reset the chip to a known state. */ sq_reset(sc); /* * Determine if we're an 8003 or 80c03 by setting the first * MAC address register to non-zero, and then reading it back. * If it's zero, we have an 80c03, because we will have read * the TxCollLSB register. */ bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0, 0xa5); if (bus_space_read_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0) == 0) sc->sc_type = SQ_TYPE_80C03; else sc->sc_type = SQ_TYPE_8003; bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0, 0x00); printf(": SGI Seeq %s\n", sc->sc_type == SQ_TYPE_80C03 ? "80c03" : "8003"); enaddr_aton(macaddr, sc->sc_enaddr); printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname, ether_sprintf(sc->sc_enaddr)); strcpy(ifp->if_xname, sc->sc_dev.dv_xname); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; ifp->if_init = sq_init; ifp->if_stop = sq_stop; ifp->if_start = sq_start; ifp->if_ioctl = sq_ioctl; ifp->if_watchdog = sq_watchdog; ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); memset(&sq_trace, 0, sizeof(sq_trace)); /* Done! */ return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[i]); m_freem(sc->sc_rxmbuf[i]); } } fail_5: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxmap[i]); } fail_4: for (i = 0; i < SQ_NTXDESC; i++) { if (sc->sc_txmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txmap[i]); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cdmap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cdmap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t) sc->sc_control, sizeof(struct sq_control)); fail_1: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg); fail_0: return; }
static void sq_attach(device_t parent, device_t self, void *aux) { int i, err; const char* macaddr; struct sq_softc *sc = device_private(self); struct hpc_attach_args *haa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; sc->sc_dev = self; sc->sc_hpct = haa->ha_st; sc->hpc_regs = haa->hpc_regs; /* HPC register definitions */ if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, sc->hpc_regs->enet_regs_size, &sc->sc_hpch)) != 0) { printf(": unable to map HPC DMA registers, error = %d\n", err); goto fail_0; } sc->sc_regt = haa->ha_st; if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, sc->hpc_regs->enet_devregs_size, &sc->sc_regh)) != 0) { printf(": unable to map Seeq registers, error = %d\n", err); goto fail_0; } sc->sc_dmat = haa->ha_dmat; if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sq_control), PAGE_SIZE, PAGE_SIZE, &sc->sc_cdseg, 1, &sc->sc_ncdseg, BUS_DMA_NOWAIT)) != 0) { printf(": unable to allocate control data, error = %d\n", err); goto fail_0; } if ((err = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg, sizeof(struct sq_control), (void **)&sc->sc_control, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { printf(": unable to map control data, error = %d\n", err); goto fail_1; } if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct sq_control), 1, sizeof(struct sq_control), PAGE_SIZE, BUS_DMA_NOWAIT, &sc->sc_cdmap)) != 0) { printf(": unable to create DMA map for control data, error " "= %d\n", err); goto fail_2; } if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cdmap, sc->sc_control, sizeof(struct sq_control), NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load DMA map for control data, error " "= %d\n", err); goto fail_3; } memset(sc->sc_control, 0, sizeof(struct sq_control)); /* Create transmit buffer DMA maps */ for (i = 0; i < SQ_NTXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_txmap[i])) != 0) { printf(": unable to create tx DMA map %d, error = %d\n", i, err); goto fail_4; } } /* Create receive buffer DMA maps */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_rxmap[i])) != 0) { printf(": unable to create rx DMA map %d, error = %d\n", i, err); goto fail_5; } } /* Pre-allocate the receive buffers. */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = sq_add_rxbuf(sc, i)) != 0) { printf(": unable to allocate or map rx buffer %d\n," " error = %d\n", i, err); goto fail_6; } } memcpy(sc->sc_enaddr, &haa->hpc_eeprom[SQ_HPC_EEPROM_ENADDR], ETHER_ADDR_LEN); /* * If our mac address is bogus, obtain it from ARCBIOS. This will * be true of the onboard HPC3 on IP22, since there is no eeprom, * but rather the DS1386 RTC's battery-backed ram is used. */ if (sc->sc_enaddr[0] != SGI_OUI_0 || sc->sc_enaddr[1] != SGI_OUI_1 || sc->sc_enaddr[2] != SGI_OUI_2) { macaddr = arcbios_GetEnvironmentVariable("eaddr"); if (macaddr == NULL) { printf(": unable to get MAC address!\n"); goto fail_6; } ether_aton_r(sc->sc_enaddr, sizeof(sc->sc_enaddr), macaddr); } evcnt_attach_dynamic(&sc->sq_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); if ((cpu_intr_establish(haa->ha_irq, IPL_NET, sq_intr, sc)) == NULL) { printf(": unable to establish interrupt!\n"); goto fail_6; } /* Reset the chip to a known state. */ sq_reset(sc); /* * Determine if we're an 8003 or 80c03 by setting the first * MAC address register to non-zero, and then reading it back. * If it's zero, we have an 80c03, because we will have read * the TxCollLSB register. */ sq_seeq_write(sc, SEEQ_TXCOLLS0, 0xa5); if (sq_seeq_read(sc, SEEQ_TXCOLLS0) == 0) sc->sc_type = SQ_TYPE_80C03; else sc->sc_type = SQ_TYPE_8003; sq_seeq_write(sc, SEEQ_TXCOLLS0, 0x00); printf(": SGI Seeq %s\n", sc->sc_type == SQ_TYPE_80C03 ? "80c03" : "8003"); printf("%s: Ethernet address %s\n", device_xname(self), ether_sprintf(sc->sc_enaddr)); strcpy(ifp->if_xname, device_xname(self)); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; ifp->if_init = sq_init; ifp->if_stop = sq_stop; ifp->if_start = sq_start; ifp->if_ioctl = sq_ioctl; ifp->if_watchdog = sq_watchdog; ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); memset(&sc->sq_trace, 0, sizeof(sc->sq_trace)); /* Done! */ return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[i]); m_freem(sc->sc_rxmbuf[i]); } } fail_5: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxmap[i]); } fail_4: for (i = 0; i < SQ_NTXDESC; i++) { if (sc->sc_txmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txmap[i]); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cdmap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cdmap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control, sizeof(struct sq_control)); fail_1: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg); fail_0: return; }
static int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *user_data, GPContext *context) { Camera *camera = user_data; int i, w, h, b, entry, frame, is_in_clip; int nb_frames, to_fetch; int do_preprocess; unsigned char comp_ratio; unsigned char *frame_data, *rawdata; unsigned char *ppm, *ptr; unsigned char gtable[256]; int size; int this_cam_tile; if (GP_FILE_TYPE_EXIF ==type) return GP_ERROR_FILE_EXISTS; if (GP_FILE_TYPE_RAW!=type && GP_FILE_TYPE_NORMAL !=type && GP_FILE_TYPE_PREVIEW!=type) { return GP_ERROR_NOT_SUPPORTED; } /* Get the entry number of the photo on the camera */ entry = -1; if (0==strcmp(folder, "/")) { i = atoi(filename+4); do { do entry++; while (sq_is_clip(camera->pl, entry) && entry<camera->pl->nb_entries); i--; } while (i>0); if (entry == camera->pl->nb_entries) return GP_ERROR_FILE_NOT_FOUND; frame = 0; is_in_clip = 0; } else { i = atoi(folder+1+4); do { do entry++; while (!sq_is_clip(camera->pl, entry) && entry<camera->pl->nb_entries); i--; } while (i>0); if (entry == camera->pl->nb_entries) return GP_ERROR_DIRECTORY_NOT_FOUND; frame = atoi(filename+4)-1; if (frame >= sq_get_num_frames(camera->pl, entry)) return GP_ERROR_FILE_NOT_FOUND; is_in_clip = 1; } GP_DEBUG ("Download file %s from %s, entry = %d, frame = %d\n", filename, folder, entry, frame); /* Fetch entries until the one we need, and toss all before * the one we need. * TODO: Either find out how to use the location info in the catalog * to download just the entry needed, or show it is as impossible as * it seems to be. */ GP_DEBUG ("last entry was %d\n", camera->pl->last_fetched_entry); /* Change register to DATA, but only if necessary */ if ((camera->pl->last_fetched_entry == -1) || ((is_in_clip) && (frame == 0)) ) sq_access_reg(camera->port, DATA); if (camera->pl->last_fetched_entry > entry) { sq_rewind(camera->port, camera->pl); } do_preprocess = 0; do { to_fetch = camera->pl->last_fetched_entry; if (to_fetch < entry) { to_fetch++; free(camera->pl->last_fetched_data); camera->pl->last_fetched_data = NULL; } nb_frames = sq_get_num_frames(camera->pl, to_fetch); comp_ratio = sq_get_comp_ratio (camera->pl, to_fetch); w = sq_get_picture_width (camera->pl, to_fetch); switch (w) { case 176: h = 144; break; case 640: h = 480; break; case 320: h = 240; break; default: h = 288; break; } b = nb_frames * w * h / comp_ratio; do_preprocess = 1; if (camera->pl->last_fetched_data) break; camera->pl->last_fetched_data = malloc (nb_frames*w*h); if (!camera->pl->last_fetched_data) { sq_rewind(camera->port, camera->pl); return GP_ERROR_NO_MEMORY; } GP_DEBUG("Fetch entry %i\n", to_fetch); sq_read_picture_data (camera->port, camera->pl->last_fetched_data, b); camera->pl->last_fetched_entry = to_fetch; } while (camera->pl->last_fetched_entry<entry); frame_data = camera->pl->last_fetched_data+(w*h)*frame/comp_ratio; /* sq_preprocess ( ) turns the photo right-side-up and for some * models must also de-mirror the photo */ if (GP_FILE_TYPE_RAW!=type) { if (do_preprocess) { sq_preprocess(camera->pl->model, comp_ratio, is_in_clip, frame_data, w, h); } /* * Now put the data into a PPM image file. */ ppm = malloc (w * h * 3 + 256); /* room for data + header */ if (!ppm) { return GP_ERROR_NO_MEMORY; } sprintf ((char *)ppm, "P6\n" "# CREATOR: gphoto2, SQ905 library\n" "%d %d\n" "255\n", w, h); size = strlen ((char *)ppm); ptr = ppm + size; switch (camera->pl->model) { case SQ_MODEL_POCK_CAM: case SQ_MODEL_MAGPIX: this_cam_tile = BAYER_TILE_GBRG; break; default: this_cam_tile = BAYER_TILE_BGGR; break; } size = size + (w * h * 3); GP_DEBUG ("size = %i\n", size); if (comp_ratio>1) { rawdata = malloc (w*h); if (!rawdata) return GP_ERROR_NO_MEMORY; sq_decompress (camera->pl->model, rawdata, frame_data, w, h); gp_gamma_fill_table (gtable, .65); } else { rawdata = frame_data; gp_gamma_fill_table (gtable, .55); } gp_ahd_decode (rawdata, w , h , ptr, this_cam_tile); gp_gamma_correct_single (gtable, ptr, w * h); gp_file_set_mime_type (file, GP_MIME_PPM); gp_file_set_data_and_size (file, (char *)ppm, size); } else { /* type is GP_FILE_TYPE_RAW */ size = w*h/comp_ratio; rawdata = malloc (size+16); if (!rawdata) return GP_ERROR_NO_MEMORY; memcpy (rawdata, frame_data, size); memcpy (rawdata+size,camera->pl->catalog+16*entry,16); gp_file_set_mime_type (file, GP_MIME_RAW); gp_file_set_data_and_size (file, (char *)rawdata, size+16); } /* Reset camera when done, for more graceful exit. */ if ((!(is_in_clip)&&(entry +1 == camera->pl->nb_entries)) || ((is_in_clip)&& (frame +1 == nb_frames ))) sq_reset (camera->port); return GP_OK; }